/* * InspIRCd -- Internet Relay Chat Daemon * * Copyright (C) 2019-2023, 2026 Sadie Powell * Copyright (C) 2013, 2015 Attila Molnar * * This file is part of InspIRCd. InspIRCd 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 . */ #pragma once #include "service.h" class CoreExport dynamic_reference_base : public insp::intrusive_list_node { public: class CaptureHook { public: /** Called when the target of the dynamic_reference has been acquired */ virtual void OnCapture() = 0; }; private: std::string service_name; std::string service_type; bool strict_ref; CaptureHook* hook = nullptr; void resolve(); static void* operator new(std::size_t) = delete; static void* operator new[](std::size_t) = delete; protected: Service::Provider* value = nullptr; public: const WeakModulePtr creator; dynamic_reference_base(const WeakModulePtr& mod, const std::string& stype, const std::string& sname, bool strict); dynamic_reference_base(const dynamic_reference_base& other); ~dynamic_reference_base(); inline const auto& GetProviderName() const { return this->service_name; } inline const auto& GetProviderType() const { return this->service_type; } void ClearProviderName(); void SetProvider(const std::string& stype, const std::string& sname); void SetProviderName(const std::string& sname); dynamic_reference_base& operator=(const dynamic_reference_base& rhs) { SetProvider(rhs.GetProviderType(), rhs.GetProviderName()); return *this; } /** Set handler to call when the target object becomes available * @param h Handler to call */ void SetCaptureHook(CaptureHook* h) { hook = h; } void check(); operator bool() const { return (value != nullptr); } static void reset_all(const std::string& stype = ""); }; inline void dynamic_reference_base::check() { if (!value) { throw ModuleException(creator, "Dynamic reference to {} {} failed to resolve. Are you missing a module?", GetProviderType(), GetProviderName()); } } template class dynamic_reference : public dynamic_reference_base { public: dynamic_reference(const WeakModulePtr& mod, const std::string& stype, const std::string& sname = "", bool strict = false) : dynamic_reference_base(mod, stype, sname, strict) { } inline T* operator->() { check(); return static_cast(value); } T* operator*() { return operator->(); } const T* operator->() const { return static_cast(value); } const T* operator*() const { return operator->(); } }; template class dynamic_reference_nocheck : public dynamic_reference_base { public: dynamic_reference_nocheck(const WeakModulePtr& mod, const std::string& stype, const std::string& sname = "", bool strict = false) : dynamic_reference_base(mod, stype, sname, strict) { } T* operator->() { return static_cast(value); } T* operator*() { return operator->(); } const T* operator->() const { return static_cast(value); } const T* operator*() const { return operator->(); } }; class ModeHandler; class ChanModeReference final : public dynamic_reference_nocheck { public: ChanModeReference(const WeakModulePtr& mod, const std::string& modename) : dynamic_reference_nocheck(mod, "ModeHandler/C", modename, true) { } }; class UserModeReference final : public dynamic_reference_nocheck { public: UserModeReference(const WeakModulePtr& mod, const std::string& modename) : dynamic_reference_nocheck(mod, "ModeHandler/U", modename, true) { } };