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