summaryrefslogtreecommitdiff
path: root/libproxy/module_manager.hpp
blob: fcca40862d23c51c91d0c380014edff7e28b4213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*******************************************************************************
 * libproxy - A library for proxy configuration
 * Copyright (C) 2009 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#ifndef MODULEMANAGER_HPP_
#define MODULEMANAGER_HPP_

#include <map>
#include <set>
#include <vector>
#include <typeinfo>
#include <algorithm>

#include "dl_module.hpp"
#include "module.hpp"

#define PX_MODULE_LOAD_NAME px_module_load
#define PX_MODULE_LOAD(type, name, cond) \
	extern "C" DLL_PUBLIC bool PX_MODULE_LOAD_NAME(module_manager& mm) { \
		if (cond) return mm.register_module<type ## _module>(new name ## _ ## type ## _module); \
		return false; \
	}

namespace com {
namespace googlecode {
namespace libproxy {
using namespace std;

class DLL_PUBLIC module_manager {
public:
	typedef bool (*LOAD_TYPE)(module_manager&);

	~module_manager();

	template <class T> vector<T*> get_modules() const {
		vector<module*> modlist = this->modules.find(&typeid(T))->second;
		vector<T*>      retlist;

		for (size_t i=0 ; i < modlist.size() ; i++)
			retlist.push_back(dynamic_cast<T*>(modlist[i]));

		return retlist;
	}

	template <class T> bool register_module(T* module)  {
		struct pcmp {
			static bool cmp(T* x, T* y) { return *x < *y; }
		};

		// If the class for this module is a singleton...
		if (this->singletons.find(&typeid(T)) != this->singletons.end()) {
			// ... and we already have an instance of this class ...
			if (this->modules[&typeid(T)].size() > 0) {
				// ... free the module and return
				delete module;
				return false;
			}
		}

		// Otherwise we just add the module and sort
		vector<T*> modlist = this->get_modules<T>();
		modlist.push_back(module);
		sort(modlist.begin(), modlist.end(), &pcmp::cmp);

		// Insert to our store
		this->modules[&typeid(T)].clear();
		for (size_t i=0 ; i < modlist.size() ; i++)
			this->modules[&typeid(T)].push_back(modlist[i]);

		return true;
	}

	template <class T> bool set_singleton(bool singleton) 	{
		if (singleton)
			return this->singletons.insert(&typeid(T)).second;
		this->singletons.erase(&typeid(T));
		return true;
	}

	bool load_file(const string filename, const string condsym="");
	bool load_dir(const string dirname);

private:
	set<dl_module*>                         dl_modules;
	map<const type_info*, vector<module*> > modules;
	set<const type_info*>                   singletons;

	bool _load(const string filename, const string initsym);
};

}
}
}

#endif /* MODULEMANAGER_HPP_ */