headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / debugger / value / TypeHandlerRoster.cpp
blob985d03cb0d04c93c884ebe1979c8e3d36cb8ff18
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "TypeHandlerRoster.h"
9 #include <new>
11 #include <AutoDeleter.h>
12 #include <AutoLocker.h>
14 #include "AddressValueNode.h"
15 #include "ArrayValueNode.h"
16 #include "CompoundValueNode.h"
17 #include "BListTypeHandler.h"
18 #include "BMessageTypeHandler.h"
19 #include "CStringTypeHandler.h"
20 #include "EnumerationValueNode.h"
21 #include "PointerToMemberValueNode.h"
22 #include "PrimitiveValueNode.h"
23 #include "Type.h"
24 #include "TypeHandler.h"
27 // #pragma mark - BasicTypeHandler
30 namespace {
33 template<typename TypeClass, typename NodeClass>
34 class BasicTypeHandler : public TypeHandler {
35 public:
36 virtual float SupportsType(Type* type)
38 return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0;
41 virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
42 Type* type, ValueNode*& _node)
44 TypeClass* supportedType = dynamic_cast<TypeClass*>(type);
45 if (supportedType == NULL)
46 return B_BAD_VALUE;
48 ValueNode* node = new(std::nothrow) NodeClass(nodeChild, supportedType);
49 if (node == NULL)
50 return B_NO_MEMORY;
52 _node = node;
53 return B_OK;
58 } // unnamed namespace
61 // #pragma mark - TypeHandlerRoster
64 /*static*/ TypeHandlerRoster* TypeHandlerRoster::sDefaultInstance = NULL;
67 TypeHandlerRoster::TypeHandlerRoster()
69 fLock("type handler roster")
74 TypeHandlerRoster::~TypeHandlerRoster()
78 /*static*/ TypeHandlerRoster*
79 TypeHandlerRoster::Default()
81 return sDefaultInstance;
85 /*static*/ status_t
86 TypeHandlerRoster::CreateDefault()
88 if (sDefaultInstance != NULL)
89 return B_OK;
91 TypeHandlerRoster* roster = new(std::nothrow) TypeHandlerRoster;
92 if (roster == NULL)
93 return B_NO_MEMORY;
94 ObjectDeleter<TypeHandlerRoster> rosterDeleter(roster);
96 status_t error = roster->Init();
97 if (error != B_OK)
98 return error;
100 error = roster->RegisterDefaultHandlers();
101 if (error != B_OK)
102 return error;
104 sDefaultInstance = rosterDeleter.Detach();
105 return B_OK;
109 /*static*/ void
110 TypeHandlerRoster::DeleteDefault()
112 TypeHandlerRoster* roster = sDefaultInstance;
113 sDefaultInstance = NULL;
114 delete roster;
118 status_t
119 TypeHandlerRoster::Init()
121 return fLock.InitCheck();
125 status_t
126 TypeHandlerRoster::RegisterDefaultHandlers()
128 TypeHandler* handler;
129 BReference<TypeHandler> handlerReference;
131 #undef REGISTER_BASIC_HANDLER
132 #define REGISTER_BASIC_HANDLER(name) \
133 handler = new(std::nothrow) \
134 BasicTypeHandler<name##Type, name##ValueNode>(); \
135 handlerReference.SetTo(handler, true); \
136 if (handler == NULL || !RegisterHandler(handler)) \
137 return B_NO_MEMORY;
139 REGISTER_BASIC_HANDLER(Address);
140 REGISTER_BASIC_HANDLER(Array);
141 REGISTER_BASIC_HANDLER(Compound);
142 REGISTER_BASIC_HANDLER(Enumeration);
143 REGISTER_BASIC_HANDLER(PointerToMember);
144 REGISTER_BASIC_HANDLER(Primitive);
146 #undef REGISTER_SPECIALIZED_HANDLER
147 #define REGISTER_SPECIALIZED_HANDLER(name) \
148 handler = new(std::nothrow) \
149 name##TypeHandler(); \
150 handlerReference.SetTo(handler, true); \
151 if (handler == NULL || !RegisterHandler(handler)) \
152 return B_NO_MEMORY;
154 REGISTER_SPECIALIZED_HANDLER(CString);
155 REGISTER_SPECIALIZED_HANDLER(BMessage);
156 REGISTER_SPECIALIZED_HANDLER(BList);
158 return B_OK;
162 status_t
163 TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type,
164 TypeHandler*& _handler)
166 // find the best-supporting handler
167 AutoLocker<BLocker> locker(fLock);
169 TypeHandler* bestHandler = NULL;
170 float bestSupport = 0;
172 for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
173 float support = handler->SupportsType(type);
174 if (support > 0 && support > bestSupport) {
175 bestHandler = handler;
176 bestSupport = support;
180 if (bestHandler == NULL)
181 return B_ENTRY_NOT_FOUND;
183 bestHandler->AcquireReference();
184 _handler = bestHandler;
185 return B_OK;
189 status_t
190 TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
191 ValueNode*& _node)
193 // find the best-supporting handler
194 while (true) {
195 TypeHandler* handler;
196 status_t error = FindTypeHandler(nodeChild, type, handler);
197 if (error == B_OK) {
198 // let the handler create the node
199 BReference<TypeHandler> handlerReference(handler, true);
200 return handler->CreateValueNode(nodeChild, type, _node);
203 // not found yet -- try to strip a modifier/typedef from the type
204 Type* nextType = type->ResolveRawType(true);
205 if (nextType == NULL || nextType == type)
206 return B_UNSUPPORTED;
208 type = nextType;
213 bool
214 TypeHandlerRoster::RegisterHandler(TypeHandler* handler)
216 if (!fTypeHandlers.AddItem(handler))
217 return false;
219 handler->AcquireReference();
220 return true;
224 void
225 TypeHandlerRoster::UnregisterHandler(TypeHandler* handler)
227 if (fTypeHandlers.RemoveItem(handler))
228 handler->ReleaseReference();