1#ifndef CRYPTOPP_OBJFACT_H
2#define CRYPTOPP_OBJFACT_H
3
4#include "cryptlib.h"
5#include <map>
6#include <vector>
7
8NAMESPACE_BEGIN(CryptoPP)
9
10//! _
11template <class AbstractClass>
12class ObjectFactory
13{
14public:
15	virtual AbstractClass * CreateObject() const =0;
16};
17
18//! _
19template <class AbstractClass, class ConcreteClass>
20class DefaultObjectFactory : public ObjectFactory<AbstractClass>
21{
22public:
23	AbstractClass * CreateObject() const
24	{
25		return new ConcreteClass;
26	}
27
28};
29
30//! _
31template <class AbstractClass, int instance=0>
32class ObjectFactoryRegistry
33{
34public:
35	class FactoryNotFound : public Exception
36	{
37	public:
38		FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name)  {}
39	};
40
41	~ObjectFactoryRegistry()
42	{
43		for (CPP_TYPENAME Map::iterator i = m_map.begin(); i != m_map.end(); ++i)
44		{
45			delete (ObjectFactory<AbstractClass> *)i->second;
46			i->second = NULL;
47		}
48	}
49
50	void RegisterFactory(const std::string &name, ObjectFactory<AbstractClass> *factory)
51	{
52		m_map[name] = factory;
53	}
54
55	const ObjectFactory<AbstractClass> * GetFactory(const char *name) const
56	{
57		CPP_TYPENAME Map::const_iterator i = m_map.find(name);
58		return i == m_map.end() ? NULL : (ObjectFactory<AbstractClass> *)i->second;
59	}
60
61	AbstractClass *CreateObject(const char *name) const
62	{
63		const ObjectFactory<AbstractClass> *factory = GetFactory(name);
64		if (!factory)
65			throw FactoryNotFound(name);
66		return factory->CreateObject();
67	}
68
69	// Return a vector containing the factory names. This is easier than returning an iterator.
70	// from Andrew Pitonyak
71	std::vector<std::string> GetFactoryNames() const
72	{
73		std::vector<std::string> names;
74		CPP_TYPENAME Map::const_iterator iter;
75		for (iter = m_map.begin(); iter != m_map.end(); ++iter)
76			names.push_back(iter->first);
77		return names;
78	}
79
80	CRYPTOPP_NOINLINE static ObjectFactoryRegistry<AbstractClass, instance> & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT);
81
82private:
83	// use void * instead of ObjectFactory<AbstractClass> * to save code size
84	typedef std::map<std::string, void *> Map;
85	Map m_map;
86};
87
88template <class AbstractClass, int instance>
89ObjectFactoryRegistry<AbstractClass, instance> & ObjectFactoryRegistry<AbstractClass, instance>::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)
90{
91	static ObjectFactoryRegistry<AbstractClass, instance> s_registry;
92	return s_registry;
93}
94
95template <class AbstractClass, class ConcreteClass, int instance = 0>
96struct RegisterDefaultFactoryFor {
97RegisterDefaultFactoryFor(const char *name=NULL)
98{
99	// BCB2006 workaround
100	std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName());
101	ObjectFactoryRegistry<AbstractClass, instance>::Registry().
102		RegisterFactory(n, new DefaultObjectFactory<AbstractClass, ConcreteClass>);
103}};
104
105template <class SchemeClass>
106void RegisterAsymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
107{
108	RegisterDefaultFactoryFor<PK_Encryptor, CPP_TYPENAME SchemeClass::Encryptor>((const char *)name);
109	RegisterDefaultFactoryFor<PK_Decryptor, CPP_TYPENAME SchemeClass::Decryptor>((const char *)name);
110}
111
112template <class SchemeClass>
113void RegisterSignatureSchemeDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
114{
115	RegisterDefaultFactoryFor<PK_Signer, CPP_TYPENAME SchemeClass::Signer>((const char *)name);
116	RegisterDefaultFactoryFor<PK_Verifier, CPP_TYPENAME SchemeClass::Verifier>((const char *)name);
117}
118
119template <class SchemeClass>
120void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
121{
122	RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
123	RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
124}
125
126template <class SchemeClass>
127void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
128{
129	RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
130	RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
131}
132
133NAMESPACE_END
134
135#endif
136