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 : #include "gdalalgorithm.h" 14 : #include "gdalalg_main.h" 15 : 16 : #include "cpl_vsi.h" 17 : 18 : #include "gdal_priv.h" 19 : 20 : #include <cassert> 21 : 22 : /************************************************************************/ 23 : /* GDALAlgorithmRegistry::~GDALAlgorithmRegistry() */ 24 : /************************************************************************/ 25 : 26 : GDALAlgorithmRegistry::~GDALAlgorithmRegistry() = default; 27 : 28 : /************************************************************************/ 29 : /* GDALAlgorithmRegistry::Register() */ 30 : /************************************************************************/ 31 : 32 15304 : bool GDALAlgorithmRegistry::Register(const GDALAlgorithmRegistry::AlgInfo &info) 33 : { 34 15304 : if (cpl::contains(m_mapNameToInfo, info.m_name)) 35 : { 36 1 : CPLError(CE_Failure, CPLE_AppDefined, 37 : "GDAL algorithm '%s' already registered!", 38 : info.m_name.c_str()); 39 1 : return false; 40 : } 41 16762 : for (const std::string &alias : info.m_aliases) 42 : { 43 2921 : if (cpl::contains(m_mapAliasToInfo, alias) || 44 1460 : cpl::contains(m_mapHiddenAliasToInfo, alias)) 45 : { 46 2 : CPLError(CE_Failure, CPLE_AppDefined, 47 : "An algorithm with alias '%s' is already registered!", 48 : alias.c_str()); 49 2 : return false; 50 : } 51 : } 52 15301 : m_mapNameToInfo[info.m_name] = info; 53 15301 : bool hidden = false; 54 16759 : for (const std::string &alias : info.m_aliases) 55 : { 56 1458 : if (alias == HIDDEN_ALIAS_SEPARATOR) 57 486 : hidden = true; 58 972 : else if (hidden) 59 971 : m_mapAliasToInfo[alias] = info; 60 : else 61 1 : m_mapHiddenAliasToInfo[alias] = info; 62 : } 63 15301 : return true; 64 : } 65 : 66 : /************************************************************************/ 67 : /* GDALAlgorithmRegistry::Instantiate() */ 68 : /************************************************************************/ 69 : 70 : std::unique_ptr<GDALAlgorithm> 71 1396 : GDALAlgorithmRegistry::Instantiate(const std::string &name) const 72 : { 73 1396 : auto iter = m_mapNameToInfo.find(name); 74 1396 : if (iter == m_mapNameToInfo.end()) 75 : { 76 39 : iter = m_mapAliasToInfo.find(name); 77 39 : if (iter == m_mapAliasToInfo.end()) 78 : { 79 37 : iter = m_mapHiddenAliasToInfo.find(name); 80 37 : if (iter == m_mapHiddenAliasToInfo.end()) 81 : { 82 37 : return nullptr; 83 : } 84 : } 85 : } 86 2718 : auto alg = iter->second.m_creationFunc(); 87 1359 : alg->m_aliases = iter->second.m_aliases; 88 1359 : return alg; 89 : } 90 : 91 : /************************************************************************/ 92 : /* GDALAlgorithmRegistry::GetNames() */ 93 : /************************************************************************/ 94 : 95 242 : std::vector<std::string> GDALAlgorithmRegistry::GetNames() const 96 : { 97 242 : std::vector<std::string> res; 98 949 : for (const auto &iter : m_mapNameToInfo) 99 : { 100 707 : res.push_back(iter.first); 101 : } 102 242 : return res; 103 : } 104 : 105 : /************************************************************************/ 106 : /* GDALGlobalAlgorithmRegistry::GetSingleton() */ 107 : /************************************************************************/ 108 : 109 : /* static */ GDALGlobalAlgorithmRegistry & 110 8009 : GDALGlobalAlgorithmRegistry::GetSingleton() 111 : { 112 8009 : static GDALGlobalAlgorithmRegistry singleton; 113 8009 : return singleton; 114 : } 115 : 116 : /************************************************************************/ 117 : /* GDALGlobalAlgorithmRegistry::Instantiate() */ 118 : /************************************************************************/ 119 : 120 : std::unique_ptr<GDALAlgorithm> 121 490 : GDALGlobalAlgorithmRegistry::Instantiate(const std::string &name) const 122 : { 123 490 : if (name == GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME) 124 88 : return std::make_unique<GDALMainAlgorithm>(); 125 804 : auto alg = GDALAlgorithmRegistry::Instantiate(name); 126 402 : if (alg) 127 : { 128 1200 : alg->SetCallPath( 129 800 : {std::string(GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME), name}); 130 : } 131 402 : return alg; 132 : } 133 : 134 : /************************************************************************/ 135 : /* struct GDALAlgorithmRegistryHS */ 136 : /************************************************************************/ 137 : 138 : struct GDALAlgorithmRegistryHS 139 : { 140 : GDALAlgorithmRegistry *ptr = nullptr; 141 : }; 142 : 143 : /************************************************************************/ 144 : /* GDALGetGlobalAlgorithmRegistry() */ 145 : /************************************************************************/ 146 : 147 : /** Gets a handle to the GDALGetGlobalAlgorithmRegistry which references 148 : * all available top-level GDAL algorithms ("raster", "vector", etc.) 149 : * 150 : * The handle must be released with GDALAlgorithmRegistryRelease() (but 151 : * this does not destroy the GDALAlgorithmRegistryRelease singleton). 152 : * 153 : * @since 3.11 154 : */ 155 387 : GDALAlgorithmRegistryH GDALGetGlobalAlgorithmRegistry() 156 : { 157 774 : auto ret = std::make_unique<GDALAlgorithmRegistryHS>(); 158 387 : ret->ptr = &(GDALGlobalAlgorithmRegistry::GetSingleton()); 159 774 : return ret.release(); 160 : } 161 : 162 : /************************************************************************/ 163 : /* GDALAlgorithmRegistryRelease() */ 164 : /************************************************************************/ 165 : 166 : /** Release a handle to an algorithm registry, but this does not destroy the 167 : * registry itself. 168 : * 169 : * @since 3.11 170 : */ 171 387 : void GDALAlgorithmRegistryRelease(GDALAlgorithmRegistryH hReg) 172 : { 173 387 : delete hReg; 174 387 : } 175 : 176 : /************************************************************************/ 177 : /* GDALAlgorithmRegistryGetAlgNames() */ 178 : /************************************************************************/ 179 : 180 : /** Return the names of the algorithms registered in the registry passed as 181 : * parameter. 182 : * 183 : * @param hReg Handle to a registry. Must NOT be null. 184 : * @return a NULL terminated list of names, which must be destroyed with 185 : * CSLDestroy() 186 : * 187 : * @since 3.11 188 : */ 189 2 : char **GDALAlgorithmRegistryGetAlgNames(GDALAlgorithmRegistryH hReg) 190 : { 191 2 : VALIDATE_POINTER1(hReg, __func__, nullptr); 192 2 : return CPLStringList(hReg->ptr->GetNames()).StealList(); 193 : } 194 : 195 : /************************************************************************/ 196 : /* GDALAlgorithmRegistryInstantiateAlg() */ 197 : /************************************************************************/ 198 : 199 : /** Instantiate an algorithm available in a registry from its name. 200 : * 201 : * @param hReg Handle to a registry. Must NOT be null. 202 : * @param pszAlgName Algorithm name. Must NOT be null. 203 : * @return an handle to the algorithm (to be freed with GDALAlgorithmRelease), 204 : * or NULL if the algorithm does not exist or another error occurred. 205 : * 206 : * @since 3.11 207 : */ 208 389 : GDALAlgorithmH GDALAlgorithmRegistryInstantiateAlg(GDALAlgorithmRegistryH hReg, 209 : const char *pszAlgName) 210 : { 211 389 : VALIDATE_POINTER1(hReg, __func__, nullptr); 212 389 : VALIDATE_POINTER1(pszAlgName, __func__, nullptr); 213 778 : auto alg = hReg->ptr->Instantiate(pszAlgName); 214 778 : return alg ? std::make_unique<GDALAlgorithmHS>(std::move(alg)).release() 215 778 : : nullptr; 216 : }