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
17 namespace Botan {
18
19 /**
20 * @param prov_name a provider name
21 * @return weight for this provider
22 */
23 size_t static_provider_weight(const std::string& prov_name);
24
25 /**
26 * Algorithm_Cache (used by Algorithm_Factory)
27 */
28 template<typename T>
29 class Algorithm_Cache
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 */
68 void clear_cache();
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 */
94 template<typename T>
95 typename Algorithm_Cache<T>::algorithms_iterator
96 Algorithm_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 */
116 template<typename T>
117 const 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 */
164 template<typename T>
165 void Algorithm_Cache<T>::add(T* algo,
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 */
189 template<typename T> std::vector<std::string>
190 Algorithm_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 */
215 template<typename T>
216 void 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 */
227 template<typename T>
228 void Algorithm_Cache<T>::clear_cache()
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
Botan::Algorithm_Cache::get
const T * get(const std::string &algo_spec, const std::string &pref_provider)
Definition: algo_cache.h:117
Botan::search_map
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
Definition: stl_util.h:43
Botan::Algorithm_Cache::providers_of
std::vector< std::string > providers_of(const std::string &algo_name)
Definition: algo_cache.h:190
Botan::Algorithm_Cache
Definition: algo_cache.h:29
Botan::static_provider_weight
size_t static_provider_weight(const std::string &prov_name)
Definition: prov_weight.cpp:15
Botan::Algorithm_Cache::add
void add(T *algo, const std::string &requested_name, const std::string &provider_name)
Definition: algo_cache.h:165
Botan::Algorithm_Cache::clear_cache
void clear_cache()
Definition: algo_cache.h:228
Botan
Definition: algo_base.h:14
Botan::Mutex
Definition: mutex.h:18
Botan::Mutex_Holder
Definition: mutex.h:50
Botan::Algorithm_Cache::~Algorithm_Cache
~Algorithm_Cache()
Definition: algo_cache.h:75
Botan::Algorithm_Cache::set_preferred_provider
void set_preferred_provider(const std::string &algo_spec, const std::string &provider)
Definition: algo_cache.h:216
Botan::Algorithm_Cache::Algorithm_Cache
Algorithm_Cache(Mutex *m)
Definition: algo_cache.h:74