diff options
Diffstat (limited to 'include/service.h')
-rw-r--r-- | include/service.h | 232 |
1 files changed, 117 insertions, 115 deletions
diff --git a/include/service.h b/include/service.h index 9c4d1f172..fd5e2245a 100644 --- a/include/service.h +++ b/include/service.h @@ -1,16 +1,24 @@ /* + * Anope IRC Services * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org + * Copyright (C) 2016 Adam <Adam@anope.org> + * Copyright (C) 2012-2016 Anope Team <team@anope.org> * - * Please read COPYING and README for further details. + * This file is part of Anope. Anope is free software; you can + * redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software + * Foundation, version 2. * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see see <http://www.gnu.org/licenses/>. */ -#ifndef SERVICE_H -#define SERVICE_H +#pragma once #include "services.h" #include "anope.h" @@ -23,151 +31,145 @@ */ class CoreExport Service : public virtual Base { - static std::map<Anope::string, std::map<Anope::string, Service *> > Services; - static std::map<Anope::string, std::map<Anope::string, Anope::string> > Aliases; - - static Service *FindService(const std::map<Anope::string, Service *> &services, const std::map<Anope::string, Anope::string> *aliases, const Anope::string &n) - { - std::map<Anope::string, Service *>::const_iterator it = services.find(n); - if (it != services.end()) - return it->second; - - if (aliases != NULL) - { - std::map<Anope::string, Anope::string>::const_iterator it2 = aliases->find(n); - if (it2 != aliases->end()) - return FindService(services, aliases, it2->second); - } - - return NULL; - } + Module *owner; + /* Service type, which should be the class name (eg "Command") */ + Anope::string type; + /* Service name, commands are usually named service/command */ + Anope::string name; public: - static Service *FindService(const Anope::string &t, const Anope::string &n) - { - std::map<Anope::string, std::map<Anope::string, Service *> >::const_iterator it = Services.find(t); - if (it == Services.end()) - return NULL; + Service(Module *o, const Anope::string &t, const Anope::string &n); + + Service(Module *o, const Anope::string &t) : Service(o, t, "") { } - std::map<Anope::string, std::map<Anope::string, Anope::string> >::const_iterator it2 = Aliases.find(t); - if (it2 != Aliases.end()) - return FindService(it->second, &it2->second, n); + virtual ~Service(); - return FindService(it->second, NULL, n); - } + Module *GetOwner() const { return owner; } - static std::vector<Anope::string> GetServiceKeys(const Anope::string &t) - { - std::vector<Anope::string> keys; - std::map<Anope::string, std::map<Anope::string, Service *> >::iterator it = Services.find(t); - if (it != Services.end()) - for (std::map<Anope::string, Service *>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) - keys.push_back(it2->first); - return keys; - } + const Anope::string &GetType() const { return type; } - static void AddAlias(const Anope::string &t, const Anope::string &n, const Anope::string &v) - { - std::map<Anope::string, Anope::string> &smap = Aliases[t]; - smap[n] = v; - } + const Anope::string &GetName() const { return name; } +}; - static void DelAlias(const Anope::string &t, const Anope::string &n) - { - std::map<Anope::string, Anope::string> &smap = Aliases[t]; - smap.erase(n); - if (smap.empty()) - Aliases.erase(t); - } +class ServiceReferenceBase +{ + Anope::string type, name; - Module *owner; - /* Service type, which should be the class name (eg "Command") */ - Anope::string type; - /* Service name, commands are usually named service/command */ - Anope::string name; + protected: + std::vector<Service *> services; - Service(Module *o, const Anope::string &t, const Anope::string &n) : owner(o), type(t), name(n) - { - this->Register(); - } + public: - virtual ~Service() - { - this->Unregister(); - } + ServiceReferenceBase() = default; - void Register() + ServiceReferenceBase(const Anope::string &_type, const Anope::string &_name); + ServiceReferenceBase(const Anope::string &_type); + + virtual ~ServiceReferenceBase(); + + explicit operator bool() const { - std::map<Anope::string, Service *> &smap = Services[this->type]; - if (smap.find(this->name) != smap.end()) - throw ModuleException("Service " + this->type + " with name " + this->name + " already exists"); - smap[this->name] = this; + return !this->services.empty(); } - void Unregister() - { - std::map<Anope::string, Service *> &smap = Services[this->type]; - smap.erase(this->name); - if (smap.empty()) - Services.erase(this->type); - } + const Anope::string &GetType() const { return type; } + const Anope::string &GetName() const { return name; } + + Service *GetService() const { return services.empty() ? nullptr : services[0]; } + const std::vector<Service *> &GetServices() const { return services; } + void SetService(Service *service); + void SetServices(const std::vector<Service *> &s); }; -/** Like Reference, but used to refer to Services. - */ template<typename T> -class ServiceReference : public Reference<T> +class ServiceReference : public ServiceReferenceBase { - Anope::string type; - Anope::string name; + static_assert(std::is_base_of<Service, T>::value, ""); public: - ServiceReference() { } + ServiceReference() : ServiceReferenceBase(T::NAME) { } + ServiceReference(const Anope::string &n) : ServiceReferenceBase(T::NAME, n) { } - ServiceReference(const Anope::string &t, const Anope::string &n) : type(t), name(n) + operator T*() const { + return static_cast<T*>(GetService()); } - inline void operator=(const Anope::string &n) + T* operator->() const { - this->name = n; - this->invalid = true; + return static_cast<T*>(GetService()); } - operator bool() anope_override + T* operator*() const { - if (this->invalid) - { - this->invalid = false; - this->ref = NULL; - } - if (!this->ref) - { - /* This really could be dynamic_cast in every case, except for when a module - * creates its own service type (that other modules must include the header file - * for), as the core is not compiled with it so there is no RTTI for it. - */ - this->ref = static_cast<T *>(::Service::FindService(this->type, this->name)); - if (this->ref) - this->ref->AddReference(this); - } - return this->ref; + return static_cast<T*>(GetService()); } }; -class ServiceAlias +template<typename T> +class ServiceReferenceList : public ServiceReferenceBase { - Anope::string t, f; + static_assert(std::is_base_of<Service, T>::value, ""); + public: - ServiceAlias(const Anope::string &type, const Anope::string &from, const Anope::string &to) : t(type), f(from) + using ServiceReferenceBase::ServiceReferenceBase; + + std::vector<T *> GetServices() const { - Service::AddAlias(type, from, to); + std::vector<T *> out; + std::transform(services.begin(), services.end(), std::back_inserter(out), [](Service *e) { return static_cast<T *>(e); }); + return out; } +}; + +class ServiceManager +{ + std::vector<ServiceReferenceBase *> references; // managed references + std::vector<Service *> services; // all registered services + + /* Lookup services for a reference */ + void Lookup(ServiceReferenceBase *reference); - ~ServiceAlias() + /* Lookup services for all managed references */ + void LookupAll(); + + std::vector<Service *> FindServices(const Anope::string &type); + + static ServiceManager *manager; + + public: + Service *FindService(const Anope::string &name); + Service *FindService(const Anope::string &type, const Anope::string &name); + + template<typename T> + std::vector<T> FindServices() { - Service::DelAlias(t, f); + static_assert(std::is_base_of<Service, typename std::remove_pointer<T>::type>::value, ""); + const char *type = std::remove_pointer<T>::type::NAME; + std::vector<Service *> s = FindServices(type); + std::vector<T> out; + std::transform(s.begin(), s.end(), std::back_inserter(out), [](Service *e) { return static_cast<T>(e); }); + return out; } + + template<typename T> + T FindService(const Anope::string &name) + { + static_assert(std::is_base_of<Service, typename std::remove_pointer<T>::type>::value, ""); + const char *type = std::remove_pointer<T>::type::NAME; + return static_cast<T>(FindService(type, name)); + } + + void Register(Service *service); + + void Unregister(Service *service); + + void RegisterReference(ServiceReferenceBase *reference); + + void UnregisterReference(ServiceReferenceBase *reference); + + static void Init(); + static ServiceManager *Get(); + static void Destroy(); }; -#endif // SERVICE_H |