diff options
Diffstat (limited to 'src/algo_factory/algo_cache.h')
-rw-r--r-- | src/algo_factory/algo_cache.h | 91 |
1 files changed, 68 insertions, 23 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h index 699078b03..17ea9964a 100644 --- a/src/algo_factory/algo_cache.h +++ b/src/algo_factory/algo_cache.h @@ -5,25 +5,46 @@ #ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ #define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ -#include <botan/scan_name.h> #include <botan/mutex.h> +#include <botan/stl_util.h> #include <string> +#include <vector> #include <map> namespace Botan { /** +* @param prov_name a provider name +* @return weight for this provider +*/ +u32bit static_provider_weight(const std::string& prov_name); + +/** * Algorithm_Cache (used by Algorithm_Factory) */ template<typename T> class Algorithm_Cache { public: - const T* get(const SCAN_Name& request); + const T* get(const std::string& algo_spec, + const std::string& pref_provider); + + /** + * Add a new algorithm implementation to the cache + */ void add(T* algo, const std::string& requested_name, - const std::string& provider); + const std::string& provider_name); + + /** + * Set the preferred provider + */ + void set_preferred_provider(const std::string& algo_spec, + const std::string& provider); + /** + * Return the list of providers of this algorithm + */ std::vector<std::string> providers_of(const std::string& algo_name); Algorithm_Cache(Mutex* m) : mutex(m) {} @@ -38,17 +59,18 @@ class Algorithm_Cache Mutex* mutex; std::map<std::string, std::string> aliases; + std::map<std::string, std::string> pref_providers; std::map<std::string, std::map<std::string, T*> > algorithms; }; /** * Look for an algorithm implementation in the cache, also checking aliases +* Assumes object lock is held */ template<typename T> typename Algorithm_Cache<T>::algorithms_iterator Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec) { - // Assumes mutex is held algorithms_iterator algo = algorithms.find(algo_spec); // Not found? Check if a known alias @@ -65,40 +87,51 @@ Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec) } /** -* Look for an algorithm implementation in the cache +* Look for an algorithm implementation by a particular provider */ template<typename T> -const T* Algorithm_Cache<T>::get(const SCAN_Name& request) +const T* Algorithm_Cache<T>::get(const std::string& algo_spec, + const std::string& requested_provider) { Mutex_Holder lock(mutex); - algorithms_iterator algo = find_algorithm(request.as_string()); - if(algo == algorithms.end()) // not found at all + algorithms_iterator algo = find_algorithm(algo_spec); + if(algo == algorithms.end()) // algo not found at all (no providers) return 0; - const std::string requested_provider = request.provider(); - + // If a provider is requested specifically, return it or fail entirely if(requested_provider != "") { - provider_iterator provider = algo->second.find(requested_provider); - - if(provider != algo->second.end()) - return provider->second; + provider_iterator prov = algo->second.find(requested_provider); + if(prov != algo->second.end()) + return prov->second; + return 0; } - else // no specific provider requested: pick one + + const T* prototype = 0; + std::string prototype_provider; + u32bit prototype_prov_weight = 0; + + const std::string pref_provider = search_map(pref_providers, algo_spec); + + for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i) { - provider_iterator provider = algo->second.begin(); + const std::string prov_name = i->first; + const u32bit prov_weight = static_provider_weight(prov_name); - while(provider != algo->second.end()) - ++provider; + // preferred prov exists, return immediately + if(prov_name == pref_provider) + return i->second; - provider = algo->second.begin(); - // @fixme: Just picks the lexicographically first one - if(provider != algo->second.end()) - return provider->second; + if(prototype == 0 || prov_weight > prototype_prov_weight) + { + prototype = i->second; + prototype_provider = i->first; + prototype_prov_weight = prov_weight; + } } - return 0; // cache miss + return prototype; } /** @@ -151,6 +184,18 @@ Algorithm_Cache<T>::providers_of(const std::string& algo_name) } /** +* Set the preferred provider for an algorithm +*/ +template<typename T> +void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec, + const std::string& provider) + { + Mutex_Holder lock(mutex); + + pref_providers[algo_spec] = provider; + } + +/** * Algorithm_Cache<T> Destructor */ template<typename T> |