Botan 1.10.17
algo_cache.h
Go to the documentation of this file.
1/*
2* An algorithm cache (used by Algorithm_Factory)
3* (C) 2008-2009,2011 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
9#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
10
11#include <botan/internal/mutex.h>
12#include <botan/internal/stl_util.h>
13#include <string>
14#include <vector>
15#include <map>
16
17namespace Botan {
18
19/**
20* @param prov_name a provider name
21* @return weight for this provider
22*/
23size_t static_provider_weight(const std::string& prov_name);
24
25/**
26* Algorithm_Cache (used by Algorithm_Factory)
27*/
28template<typename T>
30 {
31 public:
32 /**
33 * @param algo_spec names the requested algorithm
34 * @param pref_provider suggests a preferred provider
35 * @return prototype object, or NULL
36 */
37 const T* get(const std::string& algo_spec,
38 const std::string& pref_provider);
39
40 /**
41 * Add a new algorithm implementation to the cache
42 * @param algo the algorithm prototype object
43 * @param requested_name how this name will be requested
44 * @param provider_name is the name of the provider of this prototype
45 */
46 void add(T* algo,
47 const std::string& requested_name,
48 const std::string& provider_name);
49
50 /**
51 * Set the preferred provider
52 * @param algo_spec names the algorithm
53 * @param provider names the preferred provider
54 */
55 void set_preferred_provider(const std::string& algo_spec,
56 const std::string& provider);
57
58 /**
59 * Return the list of providers of this algorithm
60 * @param algo_name names the algorithm
61 * @return list of providers of this algorithm
62 */
63 std::vector<std::string> providers_of(const std::string& algo_name);
64
65 /**
66 * Clear the cache
67 */
69
70 /**
71 * Constructor
72 * @param m a mutex to serialize internal access
73 */
74 Algorithm_Cache(Mutex* m) : mutex(m) {}
75 ~Algorithm_Cache() { clear_cache(); delete mutex; }
76 private:
77 typedef typename std::map<std::string, std::map<std::string, T*> >::iterator
78 algorithms_iterator;
79
80 typedef typename std::map<std::string, T*>::iterator provider_iterator;
81
82 algorithms_iterator find_algorithm(const std::string& algo_spec);
83
84 Mutex* mutex;
85 std::map<std::string, std::string> aliases;
86 std::map<std::string, std::string> pref_providers;
87 std::map<std::string, std::map<std::string, T*> > algorithms;
88 };
89
90/*
91* Look for an algorithm implementation in the cache, also checking aliases
92* Assumes object lock is held
93*/
94template<typename T>
95typename Algorithm_Cache<T>::algorithms_iterator
96Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
97 {
98 algorithms_iterator algo = algorithms.find(algo_spec);
99
100 // Not found? Check if a known alias
101 if(algo == algorithms.end())
102 {
103 std::map<std::string, std::string>::const_iterator alias =
104 aliases.find(algo_spec);
105
106 if(alias != aliases.end())
107 algo = algorithms.find(alias->second);
108 }
109
110 return algo;
111 }
112
113/*
114* Look for an algorithm implementation by a particular provider
115*/
116template<typename T>
117const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
118 const std::string& requested_provider)
119 {
120 Mutex_Holder lock(mutex);
121
122 algorithms_iterator algo = find_algorithm(algo_spec);
123 if(algo == algorithms.end()) // algo not found at all (no providers)
124 return 0;
125
126 // If a provider is requested specifically, return it or fail entirely
127 if(requested_provider != "")
128 {
129 provider_iterator prov = algo->second.find(requested_provider);
130 if(prov != algo->second.end())
131 return prov->second;
132 return 0;
133 }
134
135 const T* prototype = 0;
136 std::string prototype_provider;
137 size_t prototype_prov_weight = 0;
138
139 const std::string pref_provider = search_map(pref_providers, algo_spec);
140
141 for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
142 {
143 const std::string prov_name = i->first;
144 const size_t prov_weight = static_provider_weight(prov_name);
145
146 // preferred prov exists, return immediately
147 if(prov_name == pref_provider)
148 return i->second;
149
150 if(prototype == 0 || prov_weight > prototype_prov_weight)
151 {
152 prototype = i->second;
153 prototype_provider = i->first;
154 prototype_prov_weight = prov_weight;
155 }
156 }
157
158 return prototype;
159 }
160
161/*
162* Add an implementation to the cache
163*/
164template<typename T>
166 const std::string& requested_name,
167 const std::string& provider)
168 {
169 if(!algo)
170 return;
171
172 Mutex_Holder lock(mutex);
173
174 if(algo->name() != requested_name &&
175 aliases.find(requested_name) == aliases.end())
176 {
177 aliases[requested_name] = algo->name();
178 }
179
180 if(!algorithms[algo->name()][provider])
181 algorithms[algo->name()][provider] = algo;
182 else
183 delete algo;
184 }
185
186/*
187* Find the providers of this algo (if any)
188*/
189template<typename T> std::vector<std::string>
190Algorithm_Cache<T>::providers_of(const std::string& algo_name)
191 {
192 Mutex_Holder lock(mutex);
193
194 std::vector<std::string> providers;
195
196 algorithms_iterator algo = find_algorithm(algo_name);
197
198 if(algo != algorithms.end())
199 {
200 provider_iterator provider = algo->second.begin();
201
202 while(provider != algo->second.end())
203 {
204 providers.push_back(provider->first);
205 ++provider;
206 }
207 }
208
209 return providers;
210 }
211
212/*
213* Set the preferred provider for an algorithm
214*/
215template<typename T>
216void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
217 const std::string& provider)
218 {
219 Mutex_Holder lock(mutex);
220
221 pref_providers[algo_spec] = provider;
222 }
223
224/*
225* Clear out the cache
226*/
227template<typename T>
229 {
230 algorithms_iterator algo = algorithms.begin();
231
232 while(algo != algorithms.end())
233 {
234 provider_iterator provider = algo->second.begin();
235
236 while(provider != algo->second.end())
237 {
238 delete provider->second;
239 ++provider;
240 }
241
242 ++algo;
243 }
244
245 algorithms.clear();
246 }
247
248}
249
250#endif
std::vector< std::string > providers_of(const std::string &algo_name)
Definition algo_cache.h:190
const T * get(const std::string &algo_spec, const std::string &pref_provider)
Definition algo_cache.h:117
void set_preferred_provider(const std::string &algo_spec, const std::string &provider)
Definition algo_cache.h:216
void add(T *algo, const std::string &requested_name, const std::string &provider_name)
Definition algo_cache.h:165
Algorithm_Cache(Mutex *m)
Definition algo_cache.h:74
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
Definition stl_util.h:43
size_t static_provider_weight(const std::string &prov_name)