/* * Anope IRC Services * * Copyright (C) 2016 Adam * Copyright (C) 2012-2017 Anope Team * * 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. * * 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 . */ #pragma once #include "services.h" #include "anope.h" #include "base.h" /** Anything that inherits from this class can be referred to * using ServiceReference. Any interfaces provided by modules, * such as commands, use this. This is also used for modules * that publish a service (m_ssl_openssl, etc). */ class CoreExport Service : public virtual Base { 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: Service(Module *o, const Anope::string &t, const Anope::string &n); Service(Module *o, const Anope::string &t) : Service(o, t, "") { } virtual ~Service(); Module *GetOwner() const { return owner; } const Anope::string &GetType() const { return type; } const Anope::string &GetName() const { return name; } }; class ServiceReferenceBase { Anope::string type, name; protected: std::vector services; public: ServiceReferenceBase() = default; ServiceReferenceBase(const Anope::string &_type, const Anope::string &_name); ServiceReferenceBase(const Anope::string &_type); virtual ~ServiceReferenceBase(); explicit operator bool() const { return !this->services.empty(); } 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 &GetServices() const { return services; } void SetService(Service *service); void SetServices(const std::vector &s); }; template class ServiceReference : public ServiceReferenceBase { static_assert(std::is_base_of::value, ""); public: ServiceReference() : ServiceReferenceBase(T::NAME) { } ServiceReference(const Anope::string &n) : ServiceReferenceBase(T::NAME, n) { } operator T*() const { return static_cast(GetService()); } T* operator->() const { return static_cast(GetService()); } T* operator*() const { return static_cast(GetService()); } }; template class ServiceReferenceList : public ServiceReferenceBase { static_assert(std::is_base_of::value, ""); public: using ServiceReferenceBase::ServiceReferenceBase; std::vector GetServices() const { std::vector out; std::transform(services.begin(), services.end(), std::back_inserter(out), [](Service *e) { return static_cast(e); }); return out; } }; class ServiceManager { std::vector references; // managed references std::vector services; // all registered services /* Lookup services for a reference */ void Lookup(ServiceReferenceBase *reference); /* Lookup services for all managed references */ void LookupAll(); std::vector 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 std::vector FindServices() { static_assert(std::is_base_of::type>::value, ""); const char *type = std::remove_pointer::type::NAME; std::vector s = FindServices(type); std::vector out; std::transform(s.begin(), s.end(), std::back_inserter(out), [](Service *e) { return static_cast(e); }); return out; } template T FindService(const Anope::string &name) { static_assert(std::is_base_of::type>::value, ""); const char *type = std::remove_pointer::type::NAME; return static_cast(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(); };