/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include #include #include class CKernel : public IKernel { class CInterfaceInfo { public: CInterfaceInfo() : m_pInterface(nullptr), m_AutoDestroy(false) { m_aName[0] = '\0'; } CInterfaceInfo(const char *pName, IInterface *pInterface, bool AutoDestroy) : m_pInterface(pInterface), m_AutoDestroy(AutoDestroy) { str_copy(m_aName, pName); } char m_aName[64]; IInterface *m_pInterface; bool m_AutoDestroy; }; std::vector m_vInterfaces; CInterfaceInfo *FindInterfaceInfo(const char *pName) { for(CInterfaceInfo &Info : m_vInterfaces) { if(str_comp(pName, Info.m_aName) == 0) return &Info; } return nullptr; } public: CKernel() = default; void Shutdown() override { for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i) { if(m_vInterfaces[i].m_AutoDestroy) { m_vInterfaces[i].m_pInterface->Shutdown(); } } } ~CKernel() override { // delete interfaces in reverse order just the way it would happen to objects on the stack for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i) { if(m_vInterfaces[i].m_AutoDestroy) { delete m_vInterfaces[i].m_pInterface; m_vInterfaces[i].m_pInterface = nullptr; } } } void RegisterInterfaceImpl(const char *pName, IInterface *pInterface, bool Destroy) override { dbg_assert(str_length(pName) < (int)sizeof(CInterfaceInfo().m_aName), "Interface name too long"); dbg_assert(FindInterfaceInfo(pName) == nullptr, "Duplicate interface name"); pInterface->m_pKernel = this; m_vInterfaces.emplace_back(pName, pInterface, Destroy); } void ReregisterInterfaceImpl(const char *pName, IInterface *pInterface) override { dbg_assert(FindInterfaceInfo(pName) != nullptr, "Cannot reregister interface that is not registered"); pInterface->m_pKernel = this; } IInterface *RequestInterfaceImpl(const char *pName) override { CInterfaceInfo *pInfo = FindInterfaceInfo(pName); dbg_assert(pInfo != nullptr, "Interface not found"); return pInfo->m_pInterface; } }; IKernel *IKernel::Create() { return new CKernel; }