#ifndef REGISTRY_H #define REGISTRY_H #include #include #include namespace encfs { template class Registry { public: typedef T *(*FactoryFn)(); struct Data { FactoryFn constructor; typename T::Properties properties; }; void Register(const char *name, FactoryFn fn, typename T::Properties properties) { Data d; d.constructor = fn; d.properties = properties; data[name] = d; } T* Create(const char *name) { auto it = data.find(name); if (it == data.end()) return NULL; return (*it->second.constructor)(); } T* CreateForMatch(const std::string &description) { for (auto &it : data) { auto name = it.second.properties.toString(); if (!name.compare(0, description.size(), description)) return (*it.second.constructor)(); } return NULL; } std::list GetAll() const { std::list result; for (auto &it : data) { result.push_back(it.first); } return result; } const typename T::Properties *GetProperties(const char *name) const { auto it = data.find(name); if (it == data.end()) return NULL; return &(it->second.properties); } const typename T::Properties *GetPropertiesForMatch( const std::string &description) const { for (auto &it : data) { auto name = it.second.properties.toString(); if (!name.compare(0, description.size(), description)) return &(it.second.properties); } return NULL; } private: std::map data; }; template class Registrar { public: Registrar(const char *name) { BASE::GetRegistry().Register(name, Registrar::Construct, T::GetProperties()); } static BASE *Construct() { return new T(); } }; #define DECLARE_REGISTERABLE_TYPE(TYPE) \ static Registry& GetRegistry() #define DEFINE_REGISTERABLE_TYPE(TYPE) \ Registry& TYPE::GetRegistry() { \ static Registry registry; \ return registry; \ } #define REGISTER_CLASS(DERIVED, BASE) \ static Registrar registrar_ ## DERIVED ## _ ## BASE (#DERIVED) } // namespace encfs #endif // REGISTRY_H