1:45 PM 11/12/2025 ���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC ‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!
Warning: Undefined variable $authorization in C:\xampp\htdocs\demo\fi.php on line 57

Warning: Undefined variable $translation in C:\xampp\htdocs\demo\fi.php on line 118

Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\demo\fi.php on line 119

Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in C:\xampp\htdocs\demo\fi.php on line 120

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 247

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 248

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 249

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 250

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 251

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 252
/****************************************************************************** * * Project: GDAL * Purpose: GDALAlgorithm C++ API * Author: Even Rouault * ****************************************************************************** * Copyright (c) 2025, Even Rouault * * SPDX-License-Identifier: MIT ****************************************************************************/ #ifndef GDAL_ALGORITHM_CPP_INCLUDED #define GDAL_ALGORITHM_CPP_INCLUDED #include "gdalalgorithm_c.h" /************************************************************************/ /************************************************************************/ /* GDAL Algorithm C++ API */ /************************************************************************/ /************************************************************************/ // This header requires C++17 // _MSC_VER >= 1920 : Visual Studio >= 2019 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && \ (defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || _MSC_VER >= 1920) #include "cpl_error.h" #include #include #include #include #include #include #include #include #include #include class GDALDataset; class OGRSpatialReference; /** Common argument category */ constexpr const char *GAAC_COMMON = "Common"; /** Base argument category */ constexpr const char *GAAC_BASE = "Base"; /** Advanced argument category */ constexpr const char *GAAC_ADVANCED = "Advanced"; /** Esoteric argument category */ constexpr const char *GAAC_ESOTERIC = "Esoteric"; /** Argument metadata item that applies to the "input-format" and * "output-format" argument */ constexpr const char *GAAMDI_REQUIRED_CAPABILITIES = "required_capabilities"; /** Argument metadata item that applies to "output-format" argument */ constexpr const char *GAAMDI_VRT_COMPATIBLE = "vrt_compatible"; /** Argument metadata item that applies to "output-format" argument */ constexpr const char *GAAMDI_ALLOWED_FORMATS = "allowed_formats"; /** Argument metadata item that applies to "output-format" argument */ constexpr const char *GAAMDI_EXCLUDED_FORMATS = "excluded_formats"; /** Name of the argument for an input dataset. */ constexpr const char *GDAL_ARG_NAME_INPUT = "input"; /** Name of the argument for the input format. */ constexpr const char *GDAL_ARG_NAME_INPUT_FORMAT = "input-format"; /** Name of the argument for the input layer. */ constexpr const char *GDAL_ARG_NAME_INPUT_LAYER = "input-layer"; /** Name of the argument for an open option. */ constexpr const char *GDAL_ARG_NAME_OPEN_OPTION = "open-option"; /** Name of the argument for an output dataset. */ constexpr const char *GDAL_ARG_NAME_OUTPUT = "output"; /** Name of the argument for an output string. */ constexpr const char *GDAL_ARG_NAME_OUTPUT_STRING = "output-string"; /** Name of the boolean argument to request outtputing directly on stdout. */ constexpr const char *GDAL_ARG_NAME_STDOUT = "stdout"; /** Name of the argument for an output format. */ constexpr const char *GDAL_ARG_NAME_OUTPUT_FORMAT = "output-format"; /** Name of the argument for the output layer. */ constexpr const char *GDAL_ARG_NAME_OUTPUT_LAYER = "output-layer"; /** Name of the argument for a creation option. */ constexpr const char *GDAL_ARG_NAME_CREATION_OPTION = "creation-option"; /** Name of the argument for a layer creation option. */ constexpr const char *GDAL_ARG_NAME_LAYER_CREATION_OPTION = "layer-creation-option"; /** Name of the argument for update. */ constexpr const char *GDAL_ARG_NAME_UPDATE = "update"; /** Name of the argument for overwriting a dataset. */ constexpr const char *GDAL_ARG_NAME_OVERWRITE = "overwrite"; /** Name of the argument for overwriting a layer. */ constexpr const char *GDAL_ARG_NAME_OVERWRITE_LAYER = "overwrite-layer"; /** Name of the argument for append. */ constexpr const char *GDAL_ARG_NAME_APPEND = "append"; /** Name of the argument for read-only. */ constexpr const char *GDAL_ARG_NAME_READ_ONLY = "read-only"; /** Name of the argument for number of threads (string). */ constexpr const char *GDAL_ARG_NAME_NUM_THREADS = "num-threads"; /** Name of the argument for number of threads (integer). */ constexpr const char *GDAL_ARG_NAME_NUM_THREADS_INT_HIDDEN = "num-threads-int-hidden"; /** Name of the argument for quiet mode. */ constexpr const char *GDAL_ARG_NAME_QUIET = "quiet"; /** Driver must expose GDAL_DCAP_RASTER or GDAL_DCAP_MULTIDIM_RASTER. * This is a potential value of GetMetadataItem(GAAMDI_REQUIRED_CAPABILITIES) */ constexpr const char *GDAL_ALG_DCAP_RASTER_OR_MULTIDIM_RASTER = "raster-or-multidim-raster"; /************************************************************************/ /* GDALArgDatasetValue */ /************************************************************************/ /** Return the string representation of GDALArgDatasetType */ std::string CPL_DLL GDALAlgorithmArgDatasetTypeName(GDALArgDatasetType); class GDALAlgorithmArg; /** Value for an argument that points to a GDALDataset. * * This is the value of arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ class CPL_DLL GDALArgDatasetValue final { public: /** Default (empty) constructor */ GDALArgDatasetValue() = default; /** Constructor by dataset name. */ explicit GDALArgDatasetValue(const std::string &name) : m_name(name), m_nameSet(true) { } /** Constructor by dataset instance, increasing its reference counter */ explicit GDALArgDatasetValue(GDALDataset *poDS); /** Move constructor */ GDALArgDatasetValue(GDALArgDatasetValue &&other); /** Destructor. Decrease m_poDS reference count, and destroy it if no * longer referenced. */ ~GDALArgDatasetValue(); /** Dereference the dataset object and close it if no longer referenced. * Return an error if an error occurred during dataset closing. */ bool Close(); /** Move-assignment operator */ GDALArgDatasetValue &operator=(GDALArgDatasetValue &&other); /** Get the GDALDataset* instance (may be null), and increase its reference * count if not null. Once done with the dataset, the caller should call * GDALDataset::Release(). */ GDALDataset *GetDatasetIncreaseRefCount(); /** Get a GDALDataset* instance (may be null). This does not modify the * reference counter, hence the lifetime of the returned object is not * guaranteed to exceed the one of this instance. */ GDALDataset *GetDatasetRef() { return m_poDS; } /** Get a GDALDataset* instance (may be null). This does not modify the * reference counter, hence the lifetime of the returned object is not * guaranteed to exceed the one of this instance. */ const GDALDataset *GetDatasetRef() const { return m_poDS; } /** Borrow the GDALDataset* instance (may be null), leaving its reference * counter unchanged. */ GDALDataset *BorrowDataset() { GDALDataset *ret = m_poDS; m_poDS = nullptr; return ret; } /** Borrow the GDALDataset* instance from another GDALArgDatasetValue, * leaving its reference counter unchanged. */ void BorrowDatasetFrom(GDALArgDatasetValue &other) { Close(); m_poDS = other.BorrowDataset(); m_name = other.m_name; } /** Get dataset name */ const std::string &GetName() const { return m_name; } /** Return whether a dataset name has been set */ bool IsNameSet() const { return m_nameSet; } /** Set dataset name */ void Set(const std::string &name); /** Transfer dataset to this instance (does not affect its reference * counter). */ void Set(std::unique_ptr poDS); /** Set dataset object, increasing its reference counter. */ void Set(GDALDataset *poDS); /** Set from other value, increasing the reference counter of the * GDALDataset object. */ void SetFrom(const GDALArgDatasetValue &other); /** Set that the dataset has been opened by the algorithm */ void SetDatasetOpenedByAlgorithm() { m_openedByAlgorithm = true; } /** Whether the dataset has been opened by the algorithm */ bool HasDatasetBeenOpenedByAlgorithm() const { return m_openedByAlgorithm; } protected: friend class GDALAlgorithm; /** Set the argument that owns us. */ void SetOwnerArgument(GDALAlgorithmArg *arg) { CPLAssert(!m_ownerArg); m_ownerArg = arg; } private: /** The owner argument (may be nullptr for freestanding objects) */ GDALAlgorithmArg *m_ownerArg = nullptr; /** Dataset object. */ GDALDataset *m_poDS = nullptr; /** Dataset name */ std::string m_name{}; /** Whether a dataset name (possibly empty for a MEM dataset...) has been set */ bool m_nameSet = false; /** Whether the dataset has been opened by the algorithm */ bool m_openedByAlgorithm = false; GDALArgDatasetValue(const GDALArgDatasetValue &) = delete; GDALArgDatasetValue &operator=(const GDALArgDatasetValue &) = delete; }; /************************************************************************/ /* GDALAlgorithmArgDecl */ /************************************************************************/ /** Argument declaration. * * It does not hold its value. */ class CPL_DLL GDALAlgorithmArgDecl final { public: /** Special value for the SetMaxCount() / GetMaxCount() to indicate * unlimited number of values. */ static constexpr int UNBOUNDED = std::numeric_limits::max(); /** Constructor. * * @param longName Long name. Must be 2 characters at least. Must not start * with dash. * @param chShortName 1-letter short name, or NUL character * @param description Description. * @param type Type of the argument. */ GDALAlgorithmArgDecl(const std::string &longName, char chShortName, const std::string &description, GDALAlgorithmArgType type); /** Declare an alias. Must be 2 characters at least. */ GDALAlgorithmArgDecl &AddAlias(const std::string &alias) { m_aliases.push_back(alias); return *this; } /** Declare a shortname alias.*/ GDALAlgorithmArgDecl &AddShortNameAlias(char shortNameAlias) { m_shortNameAliases.push_back(shortNameAlias); return *this; } /** Declare an hidden alias (i.e. not exposed in usage). * Must be 2 characters at least. */ GDALAlgorithmArgDecl &AddHiddenAlias(const std::string &alias) { m_hiddenAliases.push_back(alias); return *this; } /** Declare that the argument is positional. Typically input / output files */ GDALAlgorithmArgDecl &SetPositional() { m_positional = true; return *this; } /** Declare that the argument is required. Default is no */ GDALAlgorithmArgDecl &SetRequired() { m_required = true; return *this; } /** Declare the "meta-var" hint. * By default, the meta-var value is the long name of the argument in * upper case. */ GDALAlgorithmArgDecl &SetMetaVar(const std::string &metaVar) { m_metaVar = metaVar; return *this; } /** Declare the argument category: GAAC_COMMON, GAAC_BASE, GAAC_ADVANCED, * GAAC_ESOTERIC or a custom category. */ GDALAlgorithmArgDecl &SetCategory(const std::string &category) { m_category = category; return *this; } /** Declare a default value for the argument. */ template GDALAlgorithmArgDecl &SetDefault(const T &value) { m_hasDefaultValue = true; try { switch (m_type) { case GAAT_BOOLEAN: { if constexpr (std::is_same_v) { m_defaultValue = value; return *this; } break; } case GAAT_STRING: { if constexpr (std::is_same_v) { m_defaultValue = value; return *this; } break; } case GAAT_INTEGER: { if constexpr (std::is_same_v) { m_defaultValue = value; return *this; } break; } case GAAT_REAL: { if constexpr (std::is_assignable_v) { m_defaultValue = static_cast(value); return *this; } break; } case GAAT_STRING_LIST: { if constexpr (std::is_same_v) { m_defaultValue = std::vector{value}; return *this; } else if constexpr (std::is_same_v>) { m_defaultValue = value; return *this; } break; } case GAAT_INTEGER_LIST: { if constexpr (std::is_same_v) { m_defaultValue = std::vector{value}; return *this; } else if constexpr (std::is_same_v>) { m_defaultValue = value; return *this; } break; } case GAAT_REAL_LIST: { if constexpr (std::is_assignable_v) { m_defaultValue = std::vector{static_cast(value)}; return *this; } else if constexpr (std::is_same_v>) { m_defaultValue = value; return *this; } break; } case GAAT_DATASET: case GAAT_DATASET_LIST: break; } } catch (const std::bad_variant_access &) { // should not happen // fallthrough } CPLError(CE_Failure, CPLE_AppDefined, "Argument %s: SetDefault(): unexpected type for value", GetName().c_str()); return *this; } /** Declare a default value for the argument. */ GDALAlgorithmArgDecl &SetDefault(const char *value) { return SetDefault(std::string(value)); } /** Declare the minimum number of values for the argument. Defaults to 0. * Only applies to list type of arguments. * Setting it to non-zero does *not* make the argument required. It just * sets the minimum number of values when it is specified. To also make * it required, use SetRequired(). */ GDALAlgorithmArgDecl &SetMinCount(int count); /** Declare the maximum number of values for the argument. * Defaults to 1 for scalar types, and UNBOUNDED for list types. * Only applies to list type of arguments. */ GDALAlgorithmArgDecl &SetMaxCount(int count); /** Declare whether in \--help message one should display hints about the * minimum/maximum number of values. Defaults to true. */ GDALAlgorithmArgDecl &SetDisplayHintAboutRepetition(bool displayHint) { m_displayHintAboutRepetition = displayHint; return *this; } /** Declares whether, for list type of arguments, several values, comma * separated, may be specified. That is "--foo=bar,baz". * The default is true. */ GDALAlgorithmArgDecl &SetPackedValuesAllowed(bool allowed) { m_packedValuesAllowed = allowed; return *this; } /** Declares whether, for list type of arguments, the argument may be * repeated. That is "--foo=bar --foo=baz". * The default is true. */ GDALAlgorithmArgDecl &SetRepeatedArgAllowed(bool allowed) { m_repeatedArgAllowed = allowed; return *this; } //! @cond Doxygen_Suppress GDALAlgorithmArgDecl &SetChoices() { return *this; } //! @endcond /** Declares the allowed values (as strings) for the argument. * Only honored for GAAT_STRING and GAAT_STRING_LIST types. */ template < typename T, typename... U, typename std::enable_if &>, bool>::type = true> GDALAlgorithmArgDecl &SetChoices(T &&first, U &&...rest) { m_choices.push_back(std::forward(first)); SetChoices(std::forward(rest)...); return *this; } /** Declares the allowed values (as strings) for the argument. * Only honored for GAAT_STRING and GAAT_STRING_LIST types. */ GDALAlgorithmArgDecl &SetChoices(const std::vector &choices) { m_choices = choices; return *this; } /** Set the minimum (included) value allowed. * * Only taken into account on GAAT_INTEGER, GAAT_INTEGER_LIST, * GAAT_REAL and GAAT_REAL_LIST arguments. */ GDALAlgorithmArgDecl &SetMinValueIncluded(double min) { m_minVal = min; m_minValIsIncluded = true; return *this; } /** Set the minimum (excluded) value allowed. * * Only taken into account on GAAT_INTEGER, GAAT_INTEGER_LIST, * GAAT_REAL and GAAT_REAL_LIST arguments. */ GDALAlgorithmArgDecl &SetMinValueExcluded(double min) { m_minVal = min; m_minValIsIncluded = false; return *this; } /** Set the maximum (included) value allowed. */ GDALAlgorithmArgDecl &SetMaxValueIncluded(double max) { m_maxVal = max; m_maxValIsIncluded = true; return *this; } /** Set the maximum (excluded) value allowed. */ GDALAlgorithmArgDecl &SetMaxValueExcluded(double max) { m_maxVal = max; m_maxValIsIncluded = false; return *this; } /** Sets the minimum number of characters (for arguments of type * GAAT_STRING and GAAT_STRING_LIST) */ GDALAlgorithmArgDecl &SetMinCharCount(int count) { m_minCharCount = count; return *this; } //! @cond Doxygen_Suppress GDALAlgorithmArgDecl &SetHiddenChoices() { return *this; } //! @endcond /** Declares the, hidden, allowed values (as strings) for the argument. * Only honored for GAAT_STRING and GAAT_STRING_LIST types. */ template GDALAlgorithmArgDecl &SetHiddenChoices(T &&first, U &&...rest) { m_hiddenChoices.push_back(std::forward(first)); SetHiddenChoices(std::forward(rest)...); return *this; } /** Declare that the argument must not be mentioned in CLI usage. * For example, "output-value" for "gdal raster info", which is only * meant when the algorithm is used from a non-CLI context. */ GDALAlgorithmArgDecl &SetHiddenForCLI(bool hiddenForCLI = true) { m_hiddenForCLI = hiddenForCLI; return *this; } /** Declare that the argument is hidden in the context of an API use. * Said otherwise, if it is only for CLI usage. * For example "--help" */ GDALAlgorithmArgDecl &SetHiddenForAPI(bool hiddenForAPI = true) { m_hiddenForAPI = hiddenForAPI; return *this; } /** Declare that the argument is hidden. Default is no. * This is equivalent to calling SetHiddenForCLI() and SetHiddenForAPI() */ GDALAlgorithmArgDecl &SetHidden() { m_hiddenForCLI = true; m_hiddenForAPI = true; return *this; } /** Indicate whether the value of the argument is read-only during the * execution of the algorithm. Default is true. */ GDALAlgorithmArgDecl &SetIsInput(bool isInput = true) { m_isInput = isInput; return *this; } /** Indicate whether (at least part of) the value of the argument is set * during the execution of the algorithm. * For example, "output-value" for "gdal raster info" * Default is false. * An argument may return both IsInput() and IsOutput() as true. * For example the "gdal raster convert" algorithm consumes the dataset * name of its "output" argument, and sets the dataset object during its * execution. */ GDALAlgorithmArgDecl &SetIsOutput(bool isOutput = true) { m_isOutput = isOutput; return *this; } /** Set the name of the mutual exclusion group to which this argument * belongs to. At most one argument in a group can be specified. */ GDALAlgorithmArgDecl &SetMutualExclusionGroup(const std::string &group) { m_mutualExclusionGroup = group; return *this; } /** Set user-defined metadata item. */ GDALAlgorithmArgDecl & AddMetadataItem(const std::string &name, const std::vector &values) { m_metadata[name] = values; return *this; } /** Set that this (string) argument accepts the \@filename syntax to * mean that the content of the specified file should be used as the * value of the argument. */ GDALAlgorithmArgDecl &SetReadFromFileAtSyntaxAllowed() { m_readFromFileAtSyntaxAllowed = true; return *this; } /** Sets that SQL comments must be removed from a (string) argument. */ GDALAlgorithmArgDecl &SetRemoveSQLCommentsEnabled() { m_removeSQLComments = true; return *this; } /** Sets whether the dataset should be opened automatically by * GDALAlgorithm. Only applies to GAAT_DATASET and GAAT_DATASET_LIST. */ GDALAlgorithmArgDecl &SetAutoOpenDataset(bool autoOpen) { m_autoOpenDataset = autoOpen; return *this; } /** Declares that this argument has been created on-the-fly from user-provided * argument. */ GDALAlgorithmArgDecl &SetUserProvided() { m_userProvided = true; return *this; } /** Return the (long) name */ inline const std::string &GetName() const { return m_longName; } /** Return the short name, or empty string if there is none */ inline const std::string &GetShortName() const { return m_shortName; } /** Return the aliases (potentially none) */ inline const std::vector &GetAliases() const { return m_aliases; } /** Return the shortname aliases (potentially none) */ inline const std::vector &GetShortNameAliases() const { return m_shortNameAliases; } /** Return the description */ inline const std::string &GetDescription() const { return m_description; } /** Return the "meta-var" hint. * By default, the meta-var value is the long name of the argument in * upper case. */ inline const std::string &GetMetaVar() const { return m_metaVar; } /** Return the argument category: GAAC_COMMON, GAAC_BASE, GAAC_ADVANCED, * GAAC_ESOTERIC or a custom category. */ inline const std::string &GetCategory() const { return m_category; } /** Return the type */ inline GDALAlgorithmArgType GetType() const { return m_type; } /** Return the allowed values (as strings) for the argument. * Only honored for GAAT_STRING and GAAT_STRING_LIST types. */ inline const std::vector &GetChoices() const { return m_choices; } /** Return the allowed hidden values (as strings) for the argument. * Only honored for GAAT_STRING and GAAT_STRING_LIST types. */ inline const std::vector &GetHiddenChoices() const { return m_hiddenChoices; } /** Return the minimum value and whether it is included. */ inline std::pair GetMinValue() const { return {m_minVal, m_minValIsIncluded}; } /** Return the maximum value and whether it is included. */ inline std::pair GetMaxValue() const { return {m_maxVal, m_maxValIsIncluded}; } /** Return the minimum number of characters (for arguments of type * GAAT_STRING and GAAT_STRING_LIST) */ inline int GetMinCharCount() const { return m_minCharCount; } /** Return whether the argument is required. Defaults to false. */ inline bool IsRequired() const { return m_required; } /** Return the minimum number of values for the argument. Defaults to 0. * Only applies to list type of arguments. */ inline int GetMinCount() const { return m_minCount; } /** Return the maximum number of values for the argument. * Defaults to 1 for scalar types, and UNBOUNDED for list types. * Only applies to list type of arguments. */ inline int GetMaxCount() const { return m_maxCount; } /** Returns whether in \--help message one should display hints about the * minimum/maximum number of values. Defaults to true. */ inline bool GetDisplayHintAboutRepetition() const { return m_displayHintAboutRepetition; } /** Return whether, for list type of arguments, several values, space * separated, may be specified. That is "--foo=bar,baz". * The default is true. */ inline bool GetPackedValuesAllowed() const { return m_packedValuesAllowed; } /** Return whether, for list type of arguments, the argument may be * repeated. That is "--foo=bar --foo=baz". * The default is true. */ inline bool GetRepeatedArgAllowed() const { return m_repeatedArgAllowed; } /** Return if the argument is a positional one. */ inline bool IsPositional() const { return m_positional; } /** Return if the argument has a declared default value. */ inline bool HasDefaultValue() const { return m_hasDefaultValue; } /** Return whether the argument is hidden. */ inline bool IsHidden() const { return m_hiddenForCLI && m_hiddenForAPI; } /** Return whether the argument must not be mentioned in CLI usage. * For example, "output-value" for "gdal raster info", which is only * meant when the algorithm is used from a non-CLI context. */ inline bool IsHiddenForCLI() const { return m_hiddenForCLI; } /** Return whether the argument is only for CLI usage. * For example "--help" * This is an alias for IsHiddenForAPI() */ inline bool IsOnlyForCLI() const CPL_WARN_DEPRECATED("Use IsHiddenForAPI() instead") { return m_hiddenForAPI; } /** Return whether the argument is hidden for API usage * For example "--help" */ inline bool IsHiddenForAPI() const { return m_hiddenForAPI; } /** Indicate whether the value of the argument is read-only during the * execution of the algorithm. Default is true. */ inline bool IsInput() const { return m_isInput; } /** Return whether (at least part of) the value of the argument is set * during the execution of the algorithm. * For example, "output-value" for "gdal raster info" * Default is false. * An argument may return both IsInput() and IsOutput() as true. * For example the "gdal raster convert" algorithm consumes the dataset * name of its "output" argument, and sets the dataset object during its * execution. */ inline bool IsOutput() const { return m_isOutput; } /** Return the name of the mutual exclusion group to which this argument * belongs to, or empty string if it does not belong to any exclusion * group. */ inline const std::string &GetMutualExclusionGroup() const { return m_mutualExclusionGroup; } /** Return if this (string) argument accepts the \@filename syntax to * mean that the content of the specified file should be used as the * value of the argument. */ inline bool IsReadFromFileAtSyntaxAllowed() const { return m_readFromFileAtSyntaxAllowed; } /** Returns whether SQL comments must be removed from a (string) argument. */ bool IsRemoveSQLCommentsEnabled() const { return m_removeSQLComments; } /** Returns whether the dataset should be opened automatically by * GDALAlgorithm. Only applies to GAAT_DATASET and GAAT_DATASET_LIST. */ bool AutoOpenDataset() const { return m_autoOpenDataset; } /** Returns whether the argument has been user-provided. */ bool IsUserProvided() const { return m_userProvided; } /** Get user-defined metadata. */ inline const std::map> GetMetadata() const { return m_metadata; } /** Get user-defined metadata by item name. */ inline const std::vector * GetMetadataItem(const std::string &name) const { const auto iter = m_metadata.find(name); return iter == m_metadata.end() ? nullptr : &(iter->second); } /** Return the default value of the argument. * Must be called with T consistent of the type of the algorithm, and only * if HasDefaultValue() is true. * Valid T types are: * - bool for GAAT_BOOLEAN * - int for GAAT_INTEGER * - double for GAAT_REAL * - std::string for GAAT_STRING * - GDALArgDatasetValue for GAAT_DATASET * - std::vector for GAAT_INTEGER_LIST * - std::vector for GAAT_STRING_LIST * - std::vector for GAAT_DATASET_LIST */ template inline const T &GetDefault() const { return std::get(m_defaultValue); } /** Get which type of dataset is allowed / generated. * Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR and * GDAL_OF_MULTIDIM_RASTER, possibly combined with GDAL_OF_UPDATE. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ GDALArgDatasetType GetDatasetType() const { return m_datasetType; } /** Set which type of dataset is allowed / generated. * Binary-or combination of GDAL_OF_RASTER, GDAL_OF_VECTOR and * GDAL_OF_MULTIDIM_RASTER. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ void SetDatasetType(GDALArgDatasetType type) { m_datasetType = type; } /** Indicates which components among name and dataset are accepted as * input, when this argument serves as an input. * * If the GADV_NAME bit is set, it indicates a dataset name is accepted as * input. * If the GADV_OBJECT bit is set, it indicates a dataset object is * accepted as input. * If both bits are set, the algorithm can accept either a name or a dataset * object. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ int GetDatasetInputFlags() const { return m_datasetInputFlags; } /** Indicates which components among name and dataset are modified, * when this argument serves as an output. * * If the GADV_NAME bit is set, it indicates a dataset name is generated as * output (that is the algorithm will generate the name. Rarely used). * If the GADV_OBJECT bit is set, it indicates a dataset object is * generated as output, and available for use after the algorithm has * completed. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ int GetDatasetOutputFlags() const { return m_datasetOutputFlags; } /** Set which components among name and dataset are accepted as * input, when this argument serves as an input. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ void SetDatasetInputFlags(int flags) { m_datasetInputFlags = flags; } /** Set which components among name and dataset are modified when this * argument serves as an output. * Only applies to arguments of type GAAT_DATASET or GAAT_DATASET_LIST. */ void SetDatasetOutputFlags(int flags) { m_datasetOutputFlags = flags; } private: const std::string m_longName; const std::string m_shortName; const std::string m_description; const GDALAlgorithmArgType m_type; std::string m_category = GAAC_BASE; std::string m_metaVar{}; std::string m_mutualExclusionGroup{}; int m_minCount = 0; int m_maxCount = 0; bool m_required = false; bool m_positional = false; bool m_hasDefaultValue = false; bool m_hiddenForCLI = false; bool m_hiddenForAPI = false; bool m_isInput = true; bool m_isOutput = false; bool m_packedValuesAllowed = true; bool m_repeatedArgAllowed = true; bool m_displayHintAboutRepetition = true; bool m_readFromFileAtSyntaxAllowed = false; bool m_removeSQLComments = false; bool m_autoOpenDataset = true; bool m_userProvided = false; std::map> m_metadata{}; std::vector m_aliases{}; std::vector m_hiddenAliases{}; std::vector m_shortNameAliases{}; std::vector m_choices{}; std::vector m_hiddenChoices{}; std::variant, std::vector, std::vector> m_defaultValue{}; double m_minVal = std::numeric_limits::quiet_NaN(); double m_maxVal = std::numeric_limits::quiet_NaN(); bool m_minValIsIncluded = false; bool m_maxValIsIncluded = false; int m_minCharCount = 0; GDALArgDatasetType m_datasetType = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER; /** Which components among name and dataset are accepted as * input, when this argument serves as an input. */ int m_datasetInputFlags = GADV_NAME | GADV_OBJECT; /** Which components among name and dataset are generated as * output, when this argument serves as an output. */ int m_datasetOutputFlags = GADV_OBJECT; }; /************************************************************************/ /* GDALAlgorithmArg */ /************************************************************************/ class GDALAlgorithm; /** Argument of an algorithm. */ class CPL_DLL GDALAlgorithmArg /* non-final */ { public: /** Constructor */ template GDALAlgorithmArg(const GDALAlgorithmArgDecl &decl, T *pValue) : m_decl(decl), m_value(pValue) { if constexpr (!std::is_same_v && !std::is_same_v>) { if (decl.HasDefaultValue()) { try { *std::get(m_value) = decl.GetDefault(); } catch (const std::bad_variant_access &e) { // I don't think that can happen, but Coverity Scan thinks // so CPLError(CE_Failure, CPLE_AppDefined, "*std::get(m_value) = decl.GetDefault() " "failed: %s", e.what()); } } } } /** Destructor */ virtual ~GDALAlgorithmArg(); /** Return the argument declaration. */ const GDALAlgorithmArgDecl &GetDeclaration() const { return m_decl; } /** Alias for GDALAlgorithmArgDecl::GetName() */ inline const std::string &GetName() const { return m_decl.GetName(); } /** Alias for GDALAlgorithmArgDecl::GetShortName() */ inline const std::string &GetShortName() const { return m_decl.GetShortName(); } /** Alias for GDALAlgorithmArgDecl::GetAliases() */ inline const std::vector &GetAliases() const { return m_decl.GetAliases(); } /** Alias for GDALAlgorithmArgDecl::GetShortNameAliases() */ inline const std::vector &GetShortNameAliases() const { return m_decl.GetShortNameAliases(); } /** Alias for GDALAlgorithmArgDecl::GetDescription() */ inline const std::string &GetDescription() const { return m_decl.GetDescription(); } /** Alias for GDALAlgorithmArgDecl::GetMetaVar() */ inline const std::string &GetMetaVar() const { return m_decl.GetMetaVar(); } /** Alias for GDALAlgorithmArgDecl::GetType() */ inline GDALAlgorithmArgType GetType() const { return m_decl.GetType(); } /** Alias for GDALAlgorithmArgDecl::GetCategory() */ inline const std::string &GetCategory() const { return m_decl.GetCategory(); } /** Alias for GDALAlgorithmArgDecl::IsRequired() */ inline bool IsRequired() const { return m_decl.IsRequired(); } /** Alias for GDALAlgorithmArgDecl::GetMinCount() */ inline int GetMinCount() const { return m_decl.GetMinCount(); } /** Alias for GDALAlgorithmArgDecl::GetMaxCount() */ inline int GetMaxCount() const { return m_decl.GetMaxCount(); } /** Alias for GDALAlgorithmArgDecl::GetDisplayHintAboutRepetition() */ inline bool GetDisplayHintAboutRepetition() const { return m_decl.GetDisplayHintAboutRepetition(); } /** Alias for GDALAlgorithmArgDecl::GetPackedValuesAllowed() */ inline bool GetPackedValuesAllowed() const { return m_decl.GetPackedValuesAllowed(); } /** Alias for GDALAlgorithmArgDecl::GetRepeatedArgAllowed() */ inline bool GetRepeatedArgAllowed() const { return m_decl.GetRepeatedArgAllowed(); } /** Alias for GDALAlgorithmArgDecl::IsPositional() */ inline bool IsPositional() const { return m_decl.IsPositional(); } /** Alias for GDALAlgorithmArgDecl::GetChoices() */ inline const std::vector &GetChoices() const { return m_decl.GetChoices(); } /** Alias for GDALAlgorithmArgDecl::GetHiddenChoices() */ inline const std::vector &GetHiddenChoices() const { return m_decl.GetHiddenChoices(); } /** Return auto completion choices, if a auto completion function has been * registered. */ inline std::vector GetAutoCompleteChoices(const std::string ¤tValue) const { if (m_autoCompleteFunction) return m_autoCompleteFunction(currentValue); return {}; } /** Alias for GDALAlgorithmArgDecl::GetMinValue() */ inline std::pair GetMinValue() const { return m_decl.GetMinValue(); } /** Alias for GDALAlgorithmArgDecl::GetMaxValue() */ inline std::pair GetMaxValue() const { return m_decl.GetMaxValue(); } /** Alias for GDALAlgorithmArgDecl::GetMinCharCount() */ inline int GetMinCharCount() const { return m_decl.GetMinCharCount(); } /** Return whether the argument value has been explicitly set with Set() */ inline bool IsExplicitlySet() const { return m_explicitlySet; } /** Alias for GDALAlgorithmArgDecl::HasDefaultValue() */ inline bool HasDefaultValue() const { return m_decl.HasDefaultValue(); } /** Alias for GDALAlgorithmArgDecl::IsHidden() */ inline bool IsHidden() const { return m_decl.IsHidden(); } /** Alias for GDALAlgorithmArgDecl::IsHiddenForCLI() */ inline bool IsHiddenForCLI() const { return m_decl.IsHiddenForCLI(); } /** Alias for GDALAlgorithmArgDecl::IsOnlyForCLI() */ inline bool IsOnlyForCLI() const CPL_WARN_DEPRECATED("Use IsHiddenForAPI() instead") { return m_decl.IsHiddenForAPI(); } /** Alias for GDALAlgorithmArgDecl::IsHiddenForAPI() */ inline bool IsHiddenForAPI() const { return m_decl.IsHiddenForAPI(); } /** Alias for GDALAlgorithmArgDecl::IsInput() */ inline bool IsInput() const { return m_decl.IsInput(); } /** Alias for GDALAlgorithmArgDecl::IsOutput() */ inline bool IsOutput() const { return m_decl.IsOutput(); } /** Alias for GDALAlgorithmArgDecl::IsReadFromFileAtSyntaxAllowed() */ inline bool IsReadFromFileAtSyntaxAllowed() const { return m_decl.IsReadFromFileAtSyntaxAllowed(); } /** Alias for GDALAlgorithmArgDecl::IsRemoveSQLCommentsEnabled() */ inline bool IsRemoveSQLCommentsEnabled() const { return m_decl.IsRemoveSQLCommentsEnabled(); } /** Alias for GDALAlgorithmArgDecl::GetMutualExclusionGroup() */ inline const std::string &GetMutualExclusionGroup() const { return m_decl.GetMutualExclusionGroup(); } /** Alias for GDALAlgorithmArgDecl::GetMetadata() */ inline const std::map> GetMetadata() const { return m_decl.GetMetadata(); } /** Alias for GDALAlgorithmArgDecl::GetMetadataItem() */ inline const std::vector * GetMetadataItem(const std::string &name) const { return m_decl.GetMetadataItem(name); } /** Alias for GDALAlgorithmArgDecl::GetDefault() */ template inline const T &GetDefault() const { return m_decl.GetDefault(); } /** Alias for GDALAlgorithmArgDecl::AutoOpenDataset() */ inline bool AutoOpenDataset() const { return m_decl.AutoOpenDataset(); } /** Alias for GDALAlgorithmArgDecl::IsUserProvided() */ inline bool IsUserProvided() const { return m_decl.IsUserProvided(); } /** Alias for GDALAlgorithmArgDecl::GetDatasetType() */ inline GDALArgDatasetType GetDatasetType() const { return m_decl.GetDatasetType(); } /** Alias for GDALAlgorithmArgDecl::GetDatasetInputFlags() */ inline int GetDatasetInputFlags() const { return m_decl.GetDatasetInputFlags(); } /** Alias for GDALAlgorithmArgDecl::GetDatasetOutputFlags() */ inline int GetDatasetOutputFlags() const { return m_decl.GetDatasetOutputFlags(); } /** Return the value of the argument, which is by decreasing order of priority: * - the value set through Set(). * - the default value set through SetDefault(). * - the initial value of the C++ variable to which this argument is bound to. * * Must be called with T consistent of the type of the algorithm: * - bool for GAAT_BOOLEAN * - int for GAAT_INTEGER * - double for GAAT_REAL * - std::string for GAAT_STRING * - GDALArgDatasetValue for GAAT_DATASET * - std::vector for GAAT_INTEGER_LIST * - std::vector for GAAT_STRING_LIST * - std::vector for GAAT_DATASET_LIST */ template inline T &Get() { return *(std::get(m_value)); } /** Return the value of the argument, which is by decreasing order of priority: * - the value set through Set(). * - the default value set through SetDefault(). * - the initial value of the C++ variable to which this argument is bound to. * * Must be called with T consistent of the type of the algorithm: * - bool for GAAT_BOOLEAN * - int for GAAT_INTEGER * - double for GAAT_REAL * - std::string for GAAT_STRING * - GDALArgDatasetValue for GAAT_DATASET * - std::vector for GAAT_INTEGER_LIST * - std::vector for GAAT_STRING_LIST * - std::vector for GAAT_DATASET_LIST */ template inline const T &Get() const { return *(std::get(m_value)); } /** Set the value for a GAAT_BOOLEAN argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(bool value); /** Set the value for a GAAT_STRING argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const std::string &value); /** Set the value for a GAAT_STRING argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const char *value) { return Set(std::string(value ? value : "")); } /** Set the value for a GAAT_STRING argument from a GDALDataType * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(GDALDataType dt) { return Set(GDALGetDataTypeName(dt)); } /** Set the value for a GAAT_STRING argument (representing a CRS) * from a OGRSpatialReference * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const OGRSpatialReference &); /** Set the value for a GAAT_INTEGER (or GAAT_REAL) argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(int value); /** Set the value for a GAAT_REAL argument */ bool Set(double value); /** Set the value for a GAAT_DATASET argument, increasing ds' reference * counter if ds is not null. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(GDALDataset *ds); /** Set the value for a GAAT_DATASET argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(std::unique_ptr ds); /** Set the value for a GAAT_DATASET argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool SetDatasetName(const std::string &name); /** Set the value for a GAAT_DATASET argument. * It references the dataset pointed by other.m_poDS. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool SetFrom(const GDALArgDatasetValue &other); /** Set the value for a GAAT_STRING_LIST argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const std::vector &value); /** Set the value for a GAAT_INTEGER_LIST argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const std::vector &value); /** Set the value for a GAAT_REAL_LIST argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(const std::vector &value); /** Set the value for a GAAT_DATASET_LIST argument. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool Set(std::vector &&value); /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(bool value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(int value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(double value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const std::string &value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const char *value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(GDALDataType value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const OGRSpatialReference &value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const std::vector &value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const std::vector &value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(const std::vector &value) { Set(value); return *this; } /** Set the value of the argument. */ inline GDALAlgorithmArg &operator=(GDALDataset *value) { Set(value); return *this; } /** Set the value of the argument. */ GDALAlgorithmArg &operator=(std::unique_ptr value); /** Set the value for another argument. * For GAAT_DATASET, it will reference the dataset pointed by other.m_poDS. * It cannot be called several times for a given argument. * Validation checks and other actions are run. * Return true if success. */ bool SetFrom(const GDALAlgorithmArg &other); /** Advanced method used to make "gdal info" and "gdal raster|vector info" * to avoid re-opening an already opened dataset */ void SetSkipIfAlreadySet(bool skip = true) { m_skipIfAlreadySet = skip; } /** Advanced method used to make "gdal info" and "gdal raster|vector info" * to avoid re-opening an already opened dataset */ bool SkipIfAlreadySet() const { return m_skipIfAlreadySet; } /** Serialize this argument and its value. * May return false if the argument is not explicitly set or if a dataset * is passed by value. */ bool Serialize(std::string &serializedArg, bool absolutePath = false) const; /** Return an escaped string for argument serialization */ static std::string GetEscapedString(const std::string &s); //! @cond Doxygen_Suppress void NotifyValueSet() { m_explicitlySet = true; } //! @endcond protected: friend class GDALAlgorithm; /** Argument declaration */ GDALAlgorithmArgDecl m_decl; /** Pointer to the value */ std::variant *, std::vector *, std::vector *, std::vector *> m_value{}; /** Actions */ std::vector> m_actions{}; /** Validation actions */ std::vector> m_validationActions{}; /** Autocompletion function */ std::function(const std::string &)> m_autoCompleteFunction{}; /** Algorithm that may own this argument. */ GDALAlgorithm *m_owner = nullptr; private: bool m_skipIfAlreadySet = false; bool m_explicitlySet = false; template bool SetInternal(const T &value) { m_explicitlySet = true; *std::get(m_value) = value; return RunAllActions(); } bool ProcessString(std::string &value) const; bool RunAllActions(); void RunActions(); bool RunValidationActions(); std::string ValidateChoice(const std::string &value) const; bool ValidateIntRange(int val) const; bool ValidateRealRange(double val) const; void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...) const CPL_PRINT_FUNC_FORMAT(4, 5); CPL_DISALLOW_COPY_ASSIGN(GDALAlgorithmArg) }; /************************************************************************/ /* GDALInConstructionAlgorithmArg */ /************************************************************************/ //! @cond Doxygen_Suppress namespace test_gdal_algorithm { struct test_gdal_algorithm; } //! @endcond /** Technical class used by GDALAlgorithm when constructing argument * declarations. */ class CPL_DLL GDALInConstructionAlgorithmArg final : public GDALAlgorithmArg { friend struct test_gdal_algorithm::test_gdal_algorithm; public: /** Constructor */ template GDALInConstructionAlgorithmArg(GDALAlgorithm *owner, const GDALAlgorithmArgDecl &decl, T *pValue) : GDALAlgorithmArg(decl, pValue) { m_owner = owner; } /** Destructor */ ~GDALInConstructionAlgorithmArg() override; /** Add a documented alias for the argument */ GDALInConstructionAlgorithmArg &AddAlias(const std::string &alias); /** Add a non-documented alias for the argument */ GDALInConstructionAlgorithmArg &AddHiddenAlias(const std::string &alias); /** Add a shortname alias for the argument */ GDALInConstructionAlgorithmArg &AddShortNameAlias(char shortNameAlias); /** Alias for GDALAlgorithmArgDecl::SetPositional() */ GDALInConstructionAlgorithmArg &SetPositional(); /** Alias for GDALAlgorithmArgDecl::SetRequired() */ GDALInConstructionAlgorithmArg &SetRequired() { m_decl.SetRequired(); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMetaVar() */ GDALInConstructionAlgorithmArg &SetMetaVar(const std::string &metaVar) { m_decl.SetMetaVar(metaVar); return *this; } /** Alias for GDALAlgorithmArgDecl::SetCategory() */ GDALInConstructionAlgorithmArg &SetCategory(const std::string &category) { m_decl.SetCategory(category); return *this; } /** Alias for GDALAlgorithmArgDecl::SetDefault() */ template GDALInConstructionAlgorithmArg &SetDefault(const T &value) { m_decl.SetDefault(value); if constexpr (!std::is_same_v && !std::is_same_v>) { try { switch (m_decl.GetType()) { case GAAT_BOOLEAN: *std::get(m_value) = m_decl.GetDefault(); break; case GAAT_STRING: *std::get(m_value) = m_decl.GetDefault(); break; case GAAT_INTEGER: *std::get(m_value) = m_decl.GetDefault(); break; case GAAT_REAL: *std::get(m_value) = m_decl.GetDefault(); break; case GAAT_STRING_LIST: *std::get *>(m_value) = m_decl.GetDefault>(); break; case GAAT_INTEGER_LIST: *std::get *>(m_value) = m_decl.GetDefault>(); break; case GAAT_REAL_LIST: *std::get *>(m_value) = m_decl.GetDefault>(); break; case GAAT_DATASET: case GAAT_DATASET_LIST: break; } } catch (const std::bad_variant_access &) { // I don't think that can happen, but Coverity Scan thinks so CPLError(CE_Failure, CPLE_AppDefined, "Argument %s: SetDefault(): unexpected type for value", GetName().c_str()); } } return *this; } /** Alias for GDALAlgorithmArgDecl::SetDefault() */ GDALInConstructionAlgorithmArg &SetDefault(const char *value) { return SetDefault(std::string(value)); } /** Alias for GDALAlgorithmArgDecl::SetMinCount() */ GDALInConstructionAlgorithmArg &SetMinCount(int count) { m_decl.SetMinCount(count); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMaxCount() */ GDALInConstructionAlgorithmArg &SetMaxCount(int count) { m_decl.SetMaxCount(count); return *this; } /** Alias for GDALAlgorithmArgDecl::SetDisplayHintAboutRepetition() */ GDALInConstructionAlgorithmArg & SetDisplayHintAboutRepetition(bool displayHint) { m_decl.SetDisplayHintAboutRepetition(displayHint); return *this; } /** Alias for GDALAlgorithmArgDecl::SetPackedValuesAllowed() */ GDALInConstructionAlgorithmArg &SetPackedValuesAllowed(bool allowed) { m_decl.SetPackedValuesAllowed(allowed); return *this; } /** Alias for GDALAlgorithmArgDecl::SetRepeatedArgAllowed() */ GDALInConstructionAlgorithmArg &SetRepeatedArgAllowed(bool allowed) { m_decl.SetRepeatedArgAllowed(allowed); return *this; } /** Alias for GDALAlgorithmArgDecl::SetChoices() */ template < typename T, typename... U, typename std::enable_if &>, bool>::type = true> GDALInConstructionAlgorithmArg &SetChoices(T &&first, U &&...rest) { m_decl.SetChoices(std::forward(first), std::forward(rest)...); return *this; } /** Alias for GDALAlgorithmArgDecl::SetChoices() */ GDALInConstructionAlgorithmArg & SetChoices(const std::vector &choices) { m_decl.SetChoices(choices); return *this; } /** Alias for GDALAlgorithmArgDecl::SetHiddenChoices() */ template GDALInConstructionAlgorithmArg &SetHiddenChoices(T &&first, U &&...rest) { m_decl.SetHiddenChoices(std::forward(first), std::forward(rest)...); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMinValueIncluded() */ GDALInConstructionAlgorithmArg &SetMinValueIncluded(double min) { m_decl.SetMinValueIncluded(min); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMinValueExcluded() */ GDALInConstructionAlgorithmArg &SetMinValueExcluded(double min) { m_decl.SetMinValueExcluded(min); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMaxValueIncluded() */ GDALInConstructionAlgorithmArg &SetMaxValueIncluded(double max) { m_decl.SetMaxValueIncluded(max); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMaxValueExcluded() */ GDALInConstructionAlgorithmArg &SetMaxValueExcluded(double max) { m_decl.SetMaxValueExcluded(max); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMinCharCount() */ GDALInConstructionAlgorithmArg &SetMinCharCount(int count) { m_decl.SetMinCharCount(count); return *this; } /** Alias for GDALAlgorithmArgDecl::SetHidden() */ GDALInConstructionAlgorithmArg &SetHidden() { m_decl.SetHidden(); return *this; } /** Alias for GDALAlgorithmArgDecl::SetHiddenForCLI() */ GDALInConstructionAlgorithmArg &SetHiddenForCLI(bool hiddenForCLI = true) { m_decl.SetHiddenForCLI(hiddenForCLI); return *this; } /** Alias for GDALAlgorithmArgDecl::SetHiddenForAPI() */ GDALInConstructionAlgorithmArg &SetHiddenForAPI(bool hiddenForAPI = true) { m_decl.SetHiddenForAPI(hiddenForAPI); return *this; } /** Alias for GDALAlgorithmArgDecl::SetIsInput() */ GDALInConstructionAlgorithmArg &SetIsInput(bool isInput = true) { m_decl.SetIsInput(isInput); return *this; } /** Alias for GDALAlgorithmArgDecl::SetIsOutput() */ GDALInConstructionAlgorithmArg &SetIsOutput(bool isOutput = true) { m_decl.SetIsOutput(isOutput); return *this; } /** Alias for GDALAlgorithmArgDecl::SetReadFromFileAtSyntaxAllowed() */ GDALInConstructionAlgorithmArg &SetReadFromFileAtSyntaxAllowed() { m_decl.SetReadFromFileAtSyntaxAllowed(); return *this; } /** Alias for GDALAlgorithmArgDecl::SetRemoveSQLCommentsEnabled() */ GDALInConstructionAlgorithmArg &SetRemoveSQLCommentsEnabled() { m_decl.SetRemoveSQLCommentsEnabled(); return *this; } /** Alias for GDALAlgorithmArgDecl::SetAutoOpenDataset() */ GDALInConstructionAlgorithmArg &SetAutoOpenDataset(bool autoOpen) { m_decl.SetAutoOpenDataset(autoOpen); return *this; } /** Alias for GDALAlgorithmArgDecl::SetMutualExclusionGroup() */ GDALInConstructionAlgorithmArg & SetMutualExclusionGroup(const std::string &group) { m_decl.SetMutualExclusionGroup(group); return *this; } /** Alias for GDALAlgorithmArgDecl::AddMetadataItem() */ GDALInConstructionAlgorithmArg & AddMetadataItem(const std::string &name, const std::vector &values) { m_decl.AddMetadataItem(name, values); return *this; } /** Alias for GDALAlgorithmArgDecl::SetDatasetType() */ GDALInConstructionAlgorithmArg & SetDatasetType(GDALArgDatasetType datasetType) { m_decl.SetDatasetType(datasetType); return *this; } /** Alias for GDALAlgorithmArgDecl::SetDatasetInputFlags() */ GDALInConstructionAlgorithmArg &SetDatasetInputFlags(int flags) { m_decl.SetDatasetInputFlags(flags); return *this; } /** Alias for GDALAlgorithmArgDecl::SetDatasetOutputFlags() */ GDALInConstructionAlgorithmArg &SetDatasetOutputFlags(int flags) { m_decl.SetDatasetOutputFlags(flags); return *this; } /** Register an action that is executed, once and exactly once, if the * argument is explicitly set, at the latest by the ValidateArguments() * method. */ GDALInConstructionAlgorithmArg &AddAction(std::function f) { m_actions.push_back(f); return *this; } /** Register an action that is executed, once and exactly once, if the * argument is explicitly set, at the latest by the ValidateArguments() * method. If the provided function returns false, validation fails. * The validation function of a given argument can only check the value of * this argument, and cannot assume other arguments have already been set. */ GDALInConstructionAlgorithmArg &AddValidationAction(std::function f) { m_validationActions.push_back(f); return *this; } /** Register a function that will return a list of valid choices for * the value of the argument. This is typically used for autocompletion. */ GDALInConstructionAlgorithmArg &SetAutoCompleteFunction( std::function(const std::string &)> f) { m_autoCompleteFunction = std::move(f); return *this; } /** Register an action to validate that the argument value is a valid * CRS definition. * @param noneAllowed Set to true to mean that "null" or "none" are allowed * to mean to unset CRS. * @param specialValues List of other allowed special values. */ GDALInConstructionAlgorithmArg & SetIsCRSArg(bool noneAllowed = false, const std::vector &specialValues = std::vector()); /** Alias for GDALAlgorithmArgDecl::SetUserProvided() */ GDALInConstructionAlgorithmArg &SetUserProvided() { m_decl.SetUserProvided(); return *this; } }; /************************************************************************/ /* GDALAlgorithmRegistry */ /************************************************************************/ /** Registry of GDAL algorithms. */ class CPL_DLL GDALAlgorithmRegistry { public: /** Special value to put in m_aliases to separate public alias from * hidden aliases */ static constexpr const char *HIDDEN_ALIAS_SEPARATOR = "==hide=="; virtual ~GDALAlgorithmRegistry(); /** Algorithm information */ class AlgInfo { public: /** Algorithm (short) name */ std::string m_name{}; /** Aliases */ std::vector m_aliases{}; #ifdef DOXYGEN_SKIP /** Creation function */ std::function m_creationFunc{}; #else /** Creation function */ std::function(void)> m_creationFunc{}; #endif }; /** Register the algorithm of type MyAlgorithm. */ template bool Register() { AlgInfo info; info.m_name = MyAlgorithm::NAME; info.m_aliases = MyAlgorithm::GetAliasesStatic(); info.m_creationFunc = []() -> std::unique_ptr { return std::make_unique(); }; return Register(info); } /** Register an algorithm by its AlgInfo structure. */ bool Register(const AlgInfo &info); /** Get the names of registered algorithms. * * This only returns the main name of each algorithm, not its potential * alternate names. */ std::vector GetNames() const; /** Instantiate an algorithm by its name or one of its alias. * @return algorithm, or nullptr */ std::unique_ptr Instantiate(const std::string &name) const; /** Instantiate an algorithm by its path. * @return algorithm, or nullptr * @since 3.12 */ std::unique_ptr Instantiate(const std::vector &path) const; /** Instantiate an algorithm by its path. * @return algorithm, or nullptr * @since 3.12 */ template inline std::unique_ptr Instantiate(const std::string &first, V &&...rest) { std::vector path; return InstantiateInternal(path, first, std::forward(rest)...); } /** Get an algorithm by its name. */ const AlgInfo *GetInfo(const std::string &name) const { auto iter = m_mapNameToInfo.find(name); return iter != m_mapNameToInfo.end() ? &(iter->second) : nullptr; } /** Returns true if there are no algorithms registered. */ bool empty() const { return m_mapNameToInfo.empty(); } protected: /** Instantiate an algorithm by its name or one of its alias. */ virtual std::unique_ptr InstantiateTopLevel(const std::string &name) const; private: std::map m_mapNameToInfo{}; std::map m_mapAliasToInfo{}; std::map m_mapHiddenAliasToInfo{}; std::unique_ptr InstantiateInternal(std::vector &path); template std::unique_ptr InstantiateInternal(std::vector &path, const std::string &first, V &&...rest) { path.push_back(first); return InstantiateInternal(path, std::forward(rest)...); } }; /************************************************************************/ /* GDALAlgorithm */ /************************************************************************/ /** GDAL algorithm. * * An algorithm declares its name, description, help URL. * It also defined arguments or (mutual exclusion) sub-algorithms. * * It can be used from the command line with the ParseCommandLineArguments() * method, or users can iterate over the available arguments with the GetArgs() * or GetArg() method and fill them programmatically with * GDALAlgorithmArg::Set(). * * Execution of the algorithm is done with the Run() method. * * This is an abstract class. Implementations must sub-class it and implement the * RunImpl() method. */ /* abstract */ class CPL_DLL GDALAlgorithm { friend struct test_gdal_algorithm::test_gdal_algorithm; public: virtual ~GDALAlgorithm(); /** Get the algorithm name */ const std::string &GetName() const { return m_name; } /** Get the algorithm description (a few sentences at most) */ const std::string &GetDescription() const { return m_description; } /** Get the long algorithm description. May be empty. */ const std::string &GetLongDescription() const { return m_longDescription; } /** Get the algorithm help URL. If starting with '/', it is relative to * "https://gdal.org". */ const std::string &GetHelpURL() const { return m_helpURL; } /** Get the algorithm full URL, resolving relative URLs. */ const std::string &GetHelpFullURL() const { return m_helpFullURL; } /** Returns whether this algorithm is hidden */ bool IsHidden() const { return m_hidden; } /** Returns whether this algorithm has sub-algorithms */ bool HasSubAlgorithms() const; /** Get the names of registered algorithms. * * This only returns the main name of each algorithm, not its potential * alternate names. */ std::vector GetSubAlgorithmNames() const; /** Instantiate an algorithm by its name (or its alias). */ std::unique_ptr InstantiateSubAlgorithm(const std::string &name, bool suggestionAllowed = true) const; /** Return the potential arguments of the algorithm. */ const std::vector> &GetArgs() const { return m_args; } /** Return the potential arguments of the algorithm. */ std::vector> &GetArgs() { return m_args; } /** Return a likely matching argument using a Damerau-Levenshtein distance */ std::string GetSuggestionForArgumentName(const std::string &osName) const; /** Return an argument from its long name, short name or an alias */ GDALAlgorithmArg *GetArg(const std::string &osName, bool suggestionAllowed = false) { return GetArg(osName, suggestionAllowed, /* isConst = */ false); } /** Return an argument from its long name, short name or an alias */ GDALAlgorithmArg &operator[](const std::string &osName) { auto alg = GetArg(osName, false); if (!alg) { ReportError(CE_Failure, CPLE_AppDefined, "Argument '%s' does not exist", osName.c_str()); return m_dummyArg; } return *alg; } /** Return an argument from its long name, short name or an alias */ const GDALAlgorithmArg *GetArg(const std::string &osName, bool suggestionAllowed = false) const { return const_cast(this)->GetArg( osName, suggestionAllowed, /* isConst = */ true); } /** Return an argument from its long name, short name or an alias */ const GDALAlgorithmArg &operator[](const std::string &osName) const { const auto alg = GetArg(osName, false); if (!alg) { ReportError(CE_Failure, CPLE_AppDefined, "Argument '%s' does not exist", osName.c_str()); return m_dummyArg; } return *alg; } /** Set the calling path to this algorithm. * * For example the main "gdal" CLI will set the path to the name of its * binary before calling ParseCommandLineArguments(). */ void SetCallPath(const std::vector &path) { m_callPath = path; } /** Set hint before calling ParseCommandLineArguments() that it must * try to be be graceful when possible, e.g. accepting * "gdal raster convert in.tif out.tif --co" */ void SetParseForAutoCompletion() { m_parseForAutoCompletion = true; } /** Set the reference file paths used to interpret relative paths. * * This has only effect if called before calling ParseCommandLineArguments(). */ void SetReferencePathForRelativePaths(const std::string &referencePath) { m_referencePath = referencePath; } /** Return the reference file paths used to interpret relative paths. */ const std::string &GetReferencePathForRelativePaths() const { return m_referencePath; } /** Returns whether this algorithm supports a streamed output dataset. */ bool SupportsStreamedOutput() const { return m_supportsStreamedOutput; } /** Indicates that the algorithm must be run to generate a streamed output * dataset. In particular, this must be used as a hint by algorithms to * avoid writing files on the filesystem. This is used by the GDALG driver * when executing a serialized algorithm command line. * * This has only effect if called before calling Run(). */ void SetExecutionForStreamedOutput() { m_executionForStreamOutput = true; } /** Parse a command line argument, which does not include the algorithm * name, to set the value of corresponding arguments. */ virtual bool ParseCommandLineArguments(const std::vector &args); /** Validate that all constraints are met. * * This method may emit several errors if several constraints are not met. * * This method is automatically executed by ParseCommandLineArguments() * and Run(), and thus does generally not need to be explicitly called. * Derived classes overriding this method should generally call the base * method. */ virtual bool ValidateArguments(); /** Execute the algorithm, starting with ValidateArguments() and then * calling RunImpl(). */ bool Run(GDALProgressFunc pfnProgress = nullptr, void *pProgressData = nullptr); /** Complete any pending actions, and return the final status. * This is typically useful for algorithm that generate an output dataset. */ virtual bool Finalize(); /** Usage options */ struct UsageOptions { /** Whether this is a pipeline step */ bool isPipelineStep; /** Maximum width of the names of the options */ size_t maxOptLen; /** Whether this is a pipeline main */ bool isPipelineMain; UsageOptions() : isPipelineStep(false), maxOptLen(0), isPipelineMain(false) { } }; /** Return the usage as a string appropriate for command-line interface * \--help output. */ virtual std::string GetUsageForCLI(bool shortUsage, const UsageOptions &usageOptions = UsageOptions()) const; /** Return the usage of the algorithm as a JSON-serialized string. * * This can be used to dynamically generate interfaces to algorithms. */ virtual std::string GetUsageAsJSON() const; /** Return the actual algorithm that is going to be invoked, when the * current algorithm has sub-algorithms. * * Only valid after ParseCommandLineArguments() has been called. */ GDALAlgorithm &GetActualAlgorithm() { if (m_selectedSubAlg) return m_selectedSubAlg->GetActualAlgorithm(); return *this; } /** Whether the \--help flag has been specified. */ bool IsHelpRequested() const { return m_helpRequested; } /** Whether the \--json-usage flag has been specified. */ bool IsJSONUsageRequested() const { return m_JSONUsageRequested; } /** Whether the \--progress flag has been specified. */ bool IsProgressBarRequested() const { if (m_selectedSubAlg) return m_selectedSubAlg->IsProgressBarRequested(); return m_progressBarRequested; } /** Return alias names (generally short) for the current algorithm. */ const std::vector &GetAliases() const { return m_aliases; } //! @cond Doxygen_Suppress /** Return alias names. This method should be redefined in derived classes * that want to define aliases. */ static std::vector GetAliasesStatic() { return {}; } //! @endcond /** Used by the "gdal info" special algorithm when it first tries to * run "gdal raster info", to inherit from the potential special flags, * such as \--help or \--json-usage, that this later algorithm has received. */ bool PropagateSpecialActionTo(GDALAlgorithm *target) { target->m_calledFromCommandLine = m_calledFromCommandLine; target->m_progressBarRequested = m_progressBarRequested; target->m_quiet = m_quiet; if (m_specialActionRequested) { target->m_specialActionRequested = m_specialActionRequested; target->m_helpRequested = m_helpRequested; target->m_helpDocRequested = m_helpDocRequested; target->m_JSONUsageRequested = m_JSONUsageRequested; return true; } return false; } /** Return auto completion suggestions */ virtual std::vector GetAutoComplete(std::vector &args, bool lastWordIsComplete, bool showAllOptions); /** Set whether the algorithm is called from the command line. */ void SetCalledFromCommandLine() { m_calledFromCommandLine = true; } /** Return whether the algorithm is called from the command line. */ bool IsCalledFromCommandLine() const { return m_calledFromCommandLine; } /** Whether the algorithm generates an output string */ virtual bool HasOutputString() const; /** Save command line in a .gdalg.json file. * If filename is empty, outString will contain the serialized JSON content. */ static bool SaveGDALG(const std::string &filename, std::string &outString, const std::string &commandLine); //! @cond Doxygen_Suppress void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...) const CPL_PRINT_FUNC_FORMAT(4, 5); //! @endcond protected: friend class GDALInConstructionAlgorithmArg; friend class GDALRasterReprojectUtils; /** Selected sub-algorithm. Set by ParseCommandLineArguments() when * handling over on a sub-algorithm. */ GDALAlgorithm *m_selectedSubAlg = nullptr; /** Call path to the current algorithm. For example, for "gdal convert raster", * it is ["gdal", "convert"] */ std::vector m_callPath{}; /** Long description of the algorithm */ std::string m_longDescription{}; /** Whether a progress bar is requested (value of \--progress argument) */ bool m_progressBarRequested = true; /** Whether a progress bar is disabled (value of \--quiet argument) */ bool m_quiet = false; /** Whether ValidateArguments() should be skipped during ParseCommandLineArguments() */ bool m_skipValidationInParseCommandLine = false; friend class GDALAlgorithmRegistry; // to set m_aliases /** Algorithm alias names */ std::vector m_aliases{}; /** Whether this algorithm supports a streamed output dataset. */ bool m_supportsStreamedOutput = false; /** Whether this algorithm is run to generated a streamed output dataset. */ bool m_executionForStreamOutput = false; /** Whether this algorithm should be hidden (but can be instantiate if name known) */ bool m_hidden = false; /** Map a dataset name to its object (used for nested pipelines) */ std::map m_oMapDatasetNameToDataset{}; /** Constructor */ GDALAlgorithm(const std::string &name, const std::string &description, const std::string &helpURL); /** Special processing for an argument of type GAAT_DATASET */ bool ProcessDatasetArg(GDALAlgorithmArg *arg, GDALAlgorithm *algForOutput); /** Register the sub-algorithm of type MyAlgorithm. */ template bool RegisterSubAlgorithm() { return m_subAlgRegistry.Register(); } /** Register a sub-algoritm by its AlgInfo structure. */ bool RegisterSubAlgorithm(const GDALAlgorithmRegistry::AlgInfo &info) { return m_subAlgRegistry.Register(info); } /** Allow arbitrary user arguments using long name syntax (--something) */ void AllowArbitraryLongNameArgs() { m_arbitraryLongNameArgsAllowed = true; } /** Add boolean argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, bool *pValue); /** Add string argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, std::string *pValue); /** Add integer argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, int *pValue); /** Add real argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, double *pValue); /** Register an auto complete function for a filename argument */ static void SetAutoCompleteFunctionForFilename(GDALInConstructionAlgorithmArg &arg, GDALArgDatasetType type); /** Add dataset argument. */ GDALInConstructionAlgorithmArg & AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, GDALArgDatasetValue *pValue, GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER); /** Add list of string argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, std::vector *pValue); /** Add list of integer argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, std::vector *pValue); /** Add list of real argument. */ GDALInConstructionAlgorithmArg &AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, std::vector *pValue); /** Add list of dataset argument. */ GDALInConstructionAlgorithmArg & AddArg(const std::string &longName, char chShortName, const std::string &helpMessage, std::vector *pValue, GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER); /** Add input dataset argument. */ GDALInConstructionAlgorithmArg &AddInputDatasetArg( GDALArgDatasetValue *pValue, GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER, bool positionalAndRequired = true, const char *helpMessage = nullptr); /** Add input dataset argument. */ GDALInConstructionAlgorithmArg &AddInputDatasetArg( std::vector *pValue, GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER, bool positionalAndRequired = true, const char *helpMessage = nullptr); /** Add (input) open option(s) argument. */ GDALInConstructionAlgorithmArg & AddOpenOptionsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add output open option(s) argument. */ GDALInConstructionAlgorithmArg & AddOutputOpenOptionsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add input format(s) argument. */ GDALInConstructionAlgorithmArg & AddInputFormatsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add output dataset argument. */ GDALInConstructionAlgorithmArg &AddOutputDatasetArg( GDALArgDatasetValue *pValue, GDALArgDatasetType type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_MULTIDIM_RASTER, bool positionalAndRequired = true, const char *helpMessage = nullptr); /** Add \--overwrite argument. */ GDALInConstructionAlgorithmArg & AddOverwriteArg(bool *pValue, const char *helpMessage = nullptr); /** Add \--overwrite-layer argument. */ GDALInConstructionAlgorithmArg & AddOverwriteLayerArg(bool *pValue, const char *helpMessage = nullptr); /** Add \--update argument. */ GDALInConstructionAlgorithmArg & AddUpdateArg(bool *pValue, const char *helpMessage = nullptr); /** Add \--append argument for a vector layer. */ GDALInConstructionAlgorithmArg & AddAppendLayerArg(bool *pValue, const char *helpMessage = nullptr); /** Add (non-CLI) output-string argument. */ GDALInConstructionAlgorithmArg & AddOutputStringArg(std::string *pValue, const char *helpMessage = nullptr); /** Add (hidden) stdout argument. */ GDALInConstructionAlgorithmArg & AddStdoutArg(bool *pValue, const char *helpMessage = nullptr); /** Add output format argument. */ GDALInConstructionAlgorithmArg & AddOutputFormatArg(std::string *pValue, bool bStreamAllowed = false, bool bGDALGAllowed = false, const char *helpMessage = nullptr); /** Add output data type argument. */ GDALInConstructionAlgorithmArg & AddOutputDataTypeArg(std::string *pValue, const char *helpMessage = nullptr); /** Add nodata argument. */ GDALInConstructionAlgorithmArg & AddNodataArg(std::string *pValue, bool noneAllowed, const std::string &optionName = "nodata", const char *helpMessage = nullptr); /** Add creation option(s) argument. */ GDALInConstructionAlgorithmArg & AddCreationOptionsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add layer creation option(s) argument. */ GDALInConstructionAlgorithmArg & AddLayerCreationOptionsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add (single) layer name argument. */ GDALInConstructionAlgorithmArg & AddLayerNameArg(std::string *pValue, const char *helpMessage = nullptr); /** Add (single) output layer name argument. */ GDALInConstructionAlgorithmArg & AddOutputLayerNameArg(std::string *pValue, const char *helpMessage = nullptr); /** Add (potentially multiple) layer name(s) argument. */ GDALInConstructionAlgorithmArg & AddLayerNameArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add (single) (multidimensional) array name argument. */ GDALInConstructionAlgorithmArg & AddArrayNameArg(std::string *pValue, const char *helpMessage = nullptr); /** Add (multiple) (multidimensional) array name argument. */ GDALInConstructionAlgorithmArg & AddArrayNameArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add a memory size argument(s), The final value is stored in *pValue. * pStrValue must be provided as temporary storage, and its initial value * (if not empty) is used as the SetDefault() value. */ GDALInConstructionAlgorithmArg & AddMemorySizeArg(size_t *pValue, std::string *pStrValue, const std::string &optionName, const char *helpMessage); /** Add geometry type argument */ GDALInConstructionAlgorithmArg & AddGeometryTypeArg(std::string *pValue, const char *helpMessage = nullptr); /** Register an auto complete function for a layer name argument */ static void SetAutoCompleteFunctionForLayerName( GDALInConstructionAlgorithmArg &layerArg, GDALInConstructionAlgorithmArg &datasetArg); /** Register an auto complete function for a field name argument */ static void SetAutoCompleteFunctionForFieldName( GDALInConstructionAlgorithmArg &fieldArg, GDALInConstructionAlgorithmArg &layerNameArg, std::vector &datasetArg); /** Add a field name argument */ GDALInConstructionAlgorithmArg & AddFieldNameArg(std::string *pValue, const char *helpMessage = nullptr); /** Add a field type (or subtype) argument */ GDALInConstructionAlgorithmArg &AddFieldTypeSubtypeArg( OGRFieldType *pTypeValue, OGRFieldSubType *pSubtypeValue, std::string *pStrValue, const std::string &argName = std::string(), const char *helpMessage = nullptr); /** Add (single) band argument. */ GDALInConstructionAlgorithmArg & AddBandArg(int *pValue, const char *helpMessage = nullptr); /** Add (potentially multiple) band argument. */ GDALInConstructionAlgorithmArg & AddBandArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add bbox=xmin,ymin,xmax,ymax argument. */ GDALInConstructionAlgorithmArg & AddBBOXArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add active layer argument. */ GDALInConstructionAlgorithmArg & AddActiveLayerArg(std::string *pValue, const char *helpMessage = nullptr); /** A number of thread argument. The final value is stored in *pValue. * pStrValue must be provided as temporary storage, and its initial value * (if not empty) is used as the SetDefault() value. */ GDALInConstructionAlgorithmArg & AddNumThreadsArg(int *pValue, std::string *pStrValue, const char *helpMessage = nullptr); /** Add an argument to ask writing absolute paths. */ GDALInConstructionAlgorithmArg & AddAbsolutePathArg(bool *pValue, const char *helpMessage = nullptr); /** Add an argument for pixel function name */ GDALInConstructionAlgorithmArg & AddPixelFunctionNameArg(std::string *pValue, const char *helpMessage = nullptr); /** Add an argument for pixel function arguments */ GDALInConstructionAlgorithmArg & AddPixelFunctionArgsArg(std::vector *pValue, const char *helpMessage = nullptr); /** Add \--quiet (and hidden \--progress) argument. */ void AddProgressArg(); /** Register an action that is executed by the ValidateArguments() * method. If the provided function returns false, validation fails. * Such validation function should typically be used to ensure * cross-argument validation. For validation of individual arguments, * GDALAlgorithmArg::AddValidationAction should rather be called. */ void AddValidationAction(std::function f) { m_validationActions.push_back(f); } /** Add KEY=VALUE suggestion from open, creation options */ static bool AddOptionsSuggestions(const char *pszXML, int datasetType, const std::string ¤tValue, std::vector &oRet); /** Validation function to use for key=value type of arguments. */ bool ParseAndValidateKeyValue(GDALAlgorithmArg &arg); /** Method used by GDALRaster|VectorPipelineAlgorithm */ bool RunPreStepPipelineValidations() const; /** Return whether output-format or output arguments express GDALG output */ bool IsGDALGOutput() const; /** Return value for ProcessGDALGOutput */ enum class ProcessGDALGOutputRet { /** GDALG output requested and successful. */ GDALG_OK, /** GDALG output requested but an error has occurred. */ GDALG_ERROR, /** GDALG output not requeste. RunImpl() must be run. */ NOT_GDALG, }; /** Process output to a .gdalg file */ virtual ProcessGDALGOutputRet ProcessGDALGOutput(); /** Method executed by Run() when m_executionForStreamOutput is set to * ensure the command is safe to execute in a streamed dataset context. */ virtual bool CheckSafeForStreamOutput(); /** Validate a format argument */ bool ValidateFormat(const GDALAlgorithmArg &arg, bool bStreamAllowed, bool bGDALGAllowed) const; /** Completion function for a format argument */ static std::vector FormatAutoCompleteFunction(const GDALAlgorithmArg &arg, bool bStreamAllowed, bool bGDALGAllowed); //! @cond Doxygen_Suppress void AddAliasFor(GDALInConstructionAlgorithmArg *arg, const std::string &alias); void AddShortNameAliasFor(GDALInConstructionAlgorithmArg *arg, char shortNameAlias); void SetPositional(GDALInConstructionAlgorithmArg *arg); std::vector OpenOptionCompleteFunction(const std::string ¤tValue) const; //! @endcond /** Whether this argument name is the one of a well-known boolean argument */ static bool IsKnownOutputRelatedBooleanArgName(std::string_view osName); /** Set whether this algorithm should be reported in JSON usage. */ void SetDisplayInJSONUsage(bool b) { m_displayInJSONUsage = b; } /** Method that an algorithm can implement to issue a warning message about * its deprecation. This is called at the beginning of the Run() method. */ virtual void WarnIfDeprecated() { } /** Return the list of arguments for CLI usage */ std::pair>, size_t> GetArgNamesForCLI() const; //! @cond Doxygen_Suppress std::string GetUsageForCLIEnd() const; //! @endcond private: const std::string m_name{}; const std::string m_description{}; const std::string m_helpURL{}; const std::string m_helpFullURL{}; bool m_parsedSubStringAlreadyCalled = false; bool m_displayInJSONUsage = true; bool m_specialActionRequested = false; bool m_helpRequested = false; bool m_calledFromCommandLine = false; // Used by program-output directives in .rst files bool m_helpDocRequested = false; bool m_JSONUsageRequested = false; bool m_parseForAutoCompletion = false; std::string m_referencePath{}; std::vector m_dummyConfigOptions{}; std::vector> m_args{}; std::map m_mapLongNameToArg{}; std::map m_mapShortNameToArg{}; std::vector m_positionalArgs{}; GDALAlgorithmRegistry m_subAlgRegistry{}; std::unique_ptr m_selectedSubAlgHolder{}; std::function(const std::vector &)> m_autoCompleteFunction{}; std::vector> m_validationActions{}; std::string m_dummyVal{}; GDALAlgorithmArg m_dummyArg{ GDALAlgorithmArgDecl("dummy", 0, "", GAAT_STRING), &m_dummyVal}; /** Whether arbitrary user arguments using long name syntax (--something) * are allowed. */ bool m_arbitraryLongNameArgsAllowed = false; std::vector> m_arbitraryLongNameArgsValuesStr{}; std::vector> m_arbitraryLongNameArgsValuesBool{}; friend GDALAlgorithmArgH GDALAlgorithmGetArg(GDALAlgorithmH hAlg, const char *pszArgName); friend GDALAlgorithmArgH GDALAlgorithmGetArgNonConst(GDALAlgorithmH hAlg, const char *pszArgName); GDALAlgorithmArg *GetArg(const std::string &osName, bool suggestionAllowed, bool isConst); GDALInConstructionAlgorithmArg & AddArg(std::unique_ptr arg); bool ParseArgument( GDALAlgorithmArg *arg, const std::string &name, const std::string &value, std::map< GDALAlgorithmArg *, std::variant, std::vector, std::vector, std::vector>> &inConstructionValues); bool ValidateBandArg() const; virtual bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) = 0; /** Extract the last option and its potential value from the provided * argument list, and remove them from the list. */ void ExtractLastOptionAndValue(std::vector &args, std::string &option, std::string &value) const; std::vector AutoCompleteArrayName() const; GDALAlgorithm(const GDALAlgorithm &) = delete; GDALAlgorithm &operator=(const GDALAlgorithm &) = delete; }; //! @cond Doxygen_Suppress struct GDALAlgorithmHS { private: std::unique_ptr uniquePtr{}; GDALAlgorithmHS(const GDALAlgorithmHS &) = delete; GDALAlgorithmHS &operator=(const GDALAlgorithmHS &) = delete; public: GDALAlgorithm *ptr = nullptr; GDALAlgorithmHS() = default; explicit GDALAlgorithmHS(std::unique_ptr alg) : uniquePtr(std::move(alg)), ptr(uniquePtr.get()) { } static std::unique_ptr FromRef(GDALAlgorithm &alg) { auto ret = std::make_unique(); ret->ptr = &alg; return ret; } }; /************************************************************************/ /* GDALContainerAlgorithm */ /************************************************************************/ class CPL_DLL GDALContainerAlgorithm : public GDALAlgorithm { public: explicit GDALContainerAlgorithm( const std::string &name, const std::string &description = std::string(), const std::string &helpURL = std::string()) : GDALAlgorithm(name, description, helpURL) { } protected: bool RunImpl(GDALProgressFunc, void *) override; }; //! @endcond /************************************************************************/ /* GDALGlobalAlgorithmRegistry */ /************************************************************************/ /** Global registry of GDAL algorithms. */ class CPL_DLL GDALGlobalAlgorithmRegistry final : public GDALAlgorithmRegistry { public: /** Name of the root "gdal" algorithm. */ static constexpr const char *ROOT_ALG_NAME = "gdal"; /** Get the singleton */ static GDALGlobalAlgorithmRegistry &GetSingleton(); /** Instantiation function */ using InstantiateFunc = std::function()>; /** Declare the algorithm designed by its path (omitting leading path) * and provide its instantiation method. * For example {"driver", "pdf", "list-layers"} * * This is typically used by plugins to register extra algorithms. */ void DeclareAlgorithm(const std::vector &path, InstantiateFunc instantiateFunc); /** Return the direct declared (as per DeclareAlgorithm()) subalgorithms * of the given path. */ std::vector GetDeclaredSubAlgorithmNames(const std::vector &path) const; /** Return whether a subalgorithm is declared at the given path. */ bool HasDeclaredSubAlgorithm(const std::vector &path) const; /** Instantiate a declared (as per DeclareAlgorithm()) subalgorithm. */ std::unique_ptr InstantiateDeclaredSubAlgorithm(const std::vector &path) const; protected: std::unique_ptr InstantiateTopLevel(const std::string &name) const override; private: struct Node { InstantiateFunc instantiateFunc{}; std::map children{}; }; Node m_root{}; GDALGlobalAlgorithmRegistry(); ~GDALGlobalAlgorithmRegistry() override; const Node *GetNodeFromPath(const std::vector &path) const; }; #endif // #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && (defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || _MSC_VER >= 1920) #endif // GDAL_ALGORITHM_CPP_INCLUDED