00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
00009 #define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__
00010
00011 #include <botan/internal/mutex.h>
00012 #include <botan/internal/stl_util.h>
00013 #include <string>
00014 #include <vector>
00015 #include <map>
00016
00017 namespace Botan {
00018
00019
00020
00021
00022
00023 u32bit static_provider_weight(const std::string& prov_name);
00024
00025
00026
00027
00028 template<typename T>
00029 class Algorithm_Cache
00030 {
00031 public:
00032
00033
00034
00035
00036
00037 const T* get(const std::string& algo_spec,
00038 const std::string& pref_provider);
00039
00040
00041
00042
00043
00044
00045
00046 void add(T* algo,
00047 const std::string& requested_name,
00048 const std::string& provider_name);
00049
00050
00051
00052
00053
00054
00055 void set_preferred_provider(const std::string& algo_spec,
00056 const std::string& provider);
00057
00058
00059
00060
00061
00062
00063 std::vector<std::string> providers_of(const std::string& algo_name);
00064
00065
00066
00067
00068 void clear_cache();
00069
00070
00071
00072
00073
00074 Algorithm_Cache(Mutex* m) : mutex(m) {}
00075 ~Algorithm_Cache() { clear_cache(); delete mutex; }
00076 private:
00077 typedef typename std::map<std::string, std::map<std::string, T*> >::iterator
00078 algorithms_iterator;
00079
00080 typedef typename std::map<std::string, T*>::iterator provider_iterator;
00081
00082 algorithms_iterator find_algorithm(const std::string& algo_spec);
00083
00084 Mutex* mutex;
00085 std::map<std::string, std::string> aliases;
00086 std::map<std::string, std::string> pref_providers;
00087 std::map<std::string, std::map<std::string, T*> > algorithms;
00088 };
00089
00090
00091
00092
00093
00094 template<typename T>
00095 typename Algorithm_Cache<T>::algorithms_iterator
00096 Algorithm_Cache<T>::find_algorithm(const std::string& algo_spec)
00097 {
00098 algorithms_iterator algo = algorithms.find(algo_spec);
00099
00100
00101 if(algo == algorithms.end())
00102 {
00103 std::map<std::string, std::string>::const_iterator alias =
00104 aliases.find(algo_spec);
00105
00106 if(alias != aliases.end())
00107 algo = algorithms.find(alias->second);
00108 }
00109
00110 return algo;
00111 }
00112
00113
00114
00115
00116 template<typename T>
00117 const T* Algorithm_Cache<T>::get(const std::string& algo_spec,
00118 const std::string& requested_provider)
00119 {
00120 Mutex_Holder lock(mutex);
00121
00122 algorithms_iterator algo = find_algorithm(algo_spec);
00123 if(algo == algorithms.end())
00124 return 0;
00125
00126
00127 if(requested_provider != "")
00128 {
00129 provider_iterator prov = algo->second.find(requested_provider);
00130 if(prov != algo->second.end())
00131 return prov->second;
00132 return 0;
00133 }
00134
00135 const T* prototype = 0;
00136 std::string prototype_provider;
00137 u32bit prototype_prov_weight = 0;
00138
00139 const std::string pref_provider = search_map(pref_providers, algo_spec);
00140
00141 for(provider_iterator i = algo->second.begin(); i != algo->second.end(); ++i)
00142 {
00143 const std::string prov_name = i->first;
00144 const u32bit prov_weight = static_provider_weight(prov_name);
00145
00146
00147 if(prov_name == pref_provider)
00148 return i->second;
00149
00150 if(prototype == 0 || prov_weight > prototype_prov_weight)
00151 {
00152 prototype = i->second;
00153 prototype_provider = i->first;
00154 prototype_prov_weight = prov_weight;
00155 }
00156 }
00157
00158 return prototype;
00159 }
00160
00161
00162
00163
00164 template<typename T>
00165 void Algorithm_Cache<T>::add(T* algo,
00166 const std::string& requested_name,
00167 const std::string& provider)
00168 {
00169 if(!algo)
00170 return;
00171
00172 Mutex_Holder lock(mutex);
00173
00174 delete algorithms[algo->name()][provider];
00175 algorithms[algo->name()][provider] = algo;
00176
00177 if(algo->name() != requested_name &&
00178 aliases.find(requested_name) == aliases.end())
00179 {
00180 aliases[requested_name] = algo->name();
00181 }
00182 }
00183
00184
00185
00186
00187 template<typename T> std::vector<std::string>
00188 Algorithm_Cache<T>::providers_of(const std::string& algo_name)
00189 {
00190 Mutex_Holder lock(mutex);
00191
00192 std::vector<std::string> providers;
00193
00194 algorithms_iterator algo = find_algorithm(algo_name);
00195
00196 if(algo != algorithms.end())
00197 {
00198 provider_iterator provider = algo->second.begin();
00199
00200 while(provider != algo->second.end())
00201 {
00202 providers.push_back(provider->first);
00203 ++provider;
00204 }
00205 }
00206
00207 return providers;
00208 }
00209
00210
00211
00212
00213 template<typename T>
00214 void Algorithm_Cache<T>::set_preferred_provider(const std::string& algo_spec,
00215 const std::string& provider)
00216 {
00217 Mutex_Holder lock(mutex);
00218
00219 pref_providers[algo_spec] = provider;
00220 }
00221
00222
00223
00224
00225 template<typename T>
00226 void Algorithm_Cache<T>::clear_cache()
00227 {
00228 algorithms_iterator algo = algorithms.begin();
00229
00230 while(algo != algorithms.end())
00231 {
00232 provider_iterator provider = algo->second.begin();
00233
00234 while(provider != algo->second.end())
00235 {
00236 delete provider->second;
00237 ++provider;
00238 }
00239
00240 ++algo;
00241 }
00242
00243 algorithms.clear();
00244 }
00245
00246 }
00247
00248 #endif