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 9767 : bool GDALAlgorithmRegistry::Register(const GDALAlgorithmRegistry::AlgInfo &info) 33 : { 34 9767 : 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 10529 : for (const std::string &alias : info.m_aliases) 42 : { 43 1529 : if (cpl::contains(m_mapAliasToInfo, alias) || 44 764 : 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 9764 : m_mapNameToInfo[info.m_name] = info; 53 9764 : bool hidden = false; 54 10526 : for (const std::string &alias : info.m_aliases) 55 : { 56 762 : if (alias == HIDDEN_ALIAS_SEPARATOR) 57 254 : hidden = true; 58 508 : else if (hidden) 59 507 : m_mapAliasToInfo[alias] = info; 60 : else 61 1 : m_mapHiddenAliasToInfo[alias] = info; 62 : } 63 9764 : return true; 64 : } 65 : 66 : /************************************************************************/ 67 : /* GDALAlgorithmRegistry::Instantiate() */ 68 : /************************************************************************/ 69 : 70 : std::unique_ptr<GDALAlgorithm> 71 838 : GDALAlgorithmRegistry::Instantiate(const std::string &name) const 72 : { 73 838 : auto iter = m_mapNameToInfo.find(name); 74 838 : 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 1602 : auto alg = iter->second.m_creationFunc(); 87 801 : alg->m_aliases = iter->second.m_aliases; 88 801 : return alg; 89 : } 90 : 91 : /************************************************************************/ 92 : /* GDALAlgorithmRegistry::GetNames() */ 93 : /************************************************************************/ 94 : 95 174 : std::vector<std::string> GDALAlgorithmRegistry::GetNames() const 96 : { 97 174 : std::vector<std::string> res; 98 701 : for (const auto &iter : m_mapNameToInfo) 99 : { 100 527 : res.push_back(iter.first); 101 : } 102 174 : return res; 103 : } 104 : 105 : /************************************************************************/ 106 : /* GDALGlobalAlgorithmRegistry::GetSingleton() */ 107 : /************************************************************************/ 108 : 109 : /* static */ GDALGlobalAlgorithmRegistry & 110 7777 : GDALGlobalAlgorithmRegistry::GetSingleton() 111 : { 112 7777 : static GDALGlobalAlgorithmRegistry singleton; 113 7777 : return singleton; 114 : } 115 : 116 : /************************************************************************/ 117 : /* GDALGlobalAlgorithmRegistry::Instantiate() */ 118 : /************************************************************************/ 119 : 120 : std::unique_ptr<GDALAlgorithm> 121 273 : GDALGlobalAlgorithmRegistry::Instantiate(const std::string &name) const 122 : { 123 273 : if (name == GDALGlobalAlgorithmRegistry::ROOT_ALG_NAME) 124 73 : return std::make_unique<GDALMainAlgorithm>(); 125 200 : return GDALAlgorithmRegistry::Instantiate(name); 126 : } 127 : 128 : /************************************************************************/ 129 : /* struct GDALAlgorithmRegistryHS */ 130 : /************************************************************************/ 131 : 132 : struct GDALAlgorithmRegistryHS 133 : { 134 : GDALAlgorithmRegistry *ptr = nullptr; 135 : }; 136 : 137 : /************************************************************************/ 138 : /* GDALGetGlobalAlgorithmRegistry() */ 139 : /************************************************************************/ 140 : 141 : /** Gets a handle to the GDALGetGlobalAlgorithmRegistry which references 142 : * all available top-level GDAL algorithms ("raster", "vector", etc.) 143 : * 144 : * The handle must be released with GDALAlgorithmRegistryRelease() (but 145 : * this does not destroy the GDALAlgorithmRegistryRelease singleton). 146 : * 147 : * @since 3.11 148 : */ 149 185 : GDALAlgorithmRegistryH GDALGetGlobalAlgorithmRegistry() 150 : { 151 370 : auto ret = std::make_unique<GDALAlgorithmRegistryHS>(); 152 185 : ret->ptr = &(GDALGlobalAlgorithmRegistry::GetSingleton()); 153 370 : return ret.release(); 154 : } 155 : 156 : /************************************************************************/ 157 : /* GDALAlgorithmRegistryRelease() */ 158 : /************************************************************************/ 159 : 160 : /** Release a handle to an algorithm registry, but this does not destroy the 161 : * registry itself. 162 : * 163 : * @since 3.11 164 : */ 165 185 : void GDALAlgorithmRegistryRelease(GDALAlgorithmRegistryH hReg) 166 : { 167 185 : delete hReg; 168 185 : } 169 : 170 : /************************************************************************/ 171 : /* GDALAlgorithmRegistryGetAlgNames() */ 172 : /************************************************************************/ 173 : 174 : /** Return the names of the algorithms registered in the registry passed as 175 : * parameter. 176 : * 177 : * @param hReg Handle to a registry. Must NOT be null. 178 : * @return a NULL terminated list of names, which must be destroyed with 179 : * CSLDestroy() 180 : * 181 : * @since 3.11 182 : */ 183 2 : char **GDALAlgorithmRegistryGetAlgNames(GDALAlgorithmRegistryH hReg) 184 : { 185 2 : VALIDATE_POINTER1(hReg, __func__, nullptr); 186 2 : return CPLStringList(hReg->ptr->GetNames()).StealList(); 187 : } 188 : 189 : /************************************************************************/ 190 : /* GDALAlgorithmRegistryInstantiateAlg() */ 191 : /************************************************************************/ 192 : 193 : /** Instantiate an algorithm available in a registry from its name. 194 : * 195 : * @param hReg Handle to a registry. Must NOT be null. 196 : * @param pszAlgName Algorithm name. Must NOT be null. 197 : * @return an handle to the algorithm (to be freed with GDALAlgorithmRelease), 198 : * or NULL if the algorithm does not exist or another error occurred. 199 : * 200 : * @since 3.11 201 : */ 202 187 : GDALAlgorithmH GDALAlgorithmRegistryInstantiateAlg(GDALAlgorithmRegistryH hReg, 203 : const char *pszAlgName) 204 : { 205 187 : VALIDATE_POINTER1(hReg, __func__, nullptr); 206 187 : VALIDATE_POINTER1(pszAlgName, __func__, nullptr); 207 374 : auto alg = hReg->ptr->Instantiate(pszAlgName); 208 374 : return alg ? std::make_unique<GDALAlgorithmHS>(std::move(alg)).release() 209 374 : : nullptr; 210 : }