1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3
4#include <base/dbg.h>
5#include <base/str.h>
6
7#include <engine/kernel.h>
8
9#include <vector>
10
11class CKernel : public IKernel
12{
13 class CInterfaceInfo
14 {
15 public:
16 CInterfaceInfo() :
17 m_pInterface(nullptr),
18 m_AutoDestroy(false)
19 {
20 m_aName[0] = '\0';
21 }
22
23 CInterfaceInfo(const char *pName, IInterface *pInterface, bool AutoDestroy) :
24 m_pInterface(pInterface),
25 m_AutoDestroy(AutoDestroy)
26 {
27 str_copy(dst&: m_aName, src: pName);
28 }
29
30 char m_aName[64];
31 IInterface *m_pInterface;
32 bool m_AutoDestroy;
33 };
34
35 std::vector<CInterfaceInfo> m_vInterfaces;
36
37 CInterfaceInfo *FindInterfaceInfo(const char *pName)
38 {
39 for(CInterfaceInfo &Info : m_vInterfaces)
40 {
41 if(str_comp(a: pName, b: Info.m_aName) == 0)
42 return &Info;
43 }
44 return nullptr;
45 }
46
47public:
48 CKernel() = default;
49
50 void Shutdown() override
51 {
52 for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i)
53 {
54 if(m_vInterfaces[i].m_AutoDestroy)
55 {
56 m_vInterfaces[i].m_pInterface->Shutdown();
57 }
58 }
59 }
60
61 ~CKernel() override
62 {
63 // delete interfaces in reverse order just the way it would happen to objects on the stack
64 for(int i = (int)m_vInterfaces.size() - 1; i >= 0; --i)
65 {
66 if(m_vInterfaces[i].m_AutoDestroy)
67 {
68 delete m_vInterfaces[i].m_pInterface;
69 m_vInterfaces[i].m_pInterface = nullptr;
70 }
71 }
72 }
73
74 void RegisterInterfaceImpl(const char *pName, IInterface *pInterface, bool Destroy) override
75 {
76 dbg_assert(str_length(pName) < (int)sizeof(CInterfaceInfo().m_aName), "Interface name too long");
77 dbg_assert(FindInterfaceInfo(pName) == nullptr, "Duplicate interface name");
78
79 pInterface->m_pKernel = this;
80 m_vInterfaces.emplace_back(args&: pName, args&: pInterface, args&: Destroy);
81 }
82
83 void ReregisterInterfaceImpl(const char *pName, IInterface *pInterface) override
84 {
85 dbg_assert(FindInterfaceInfo(pName) != nullptr, "Cannot reregister interface that is not registered");
86 pInterface->m_pKernel = this;
87 }
88
89 IInterface *RequestInterfaceImpl(const char *pName) override
90 {
91 CInterfaceInfo *pInfo = FindInterfaceInfo(pName);
92 dbg_assert(pInfo != nullptr, "Interface '%s' not found", pName);
93 return pInfo->m_pInterface;
94 }
95};
96
97IKernel *IKernel::Create() { return new CKernel; }
98