1/* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2018, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8#include "TypeHandlerRoster.h" 9 10#include <new> 11 12#include <AutoDeleter.h> 13#include <AutoLocker.h> 14 15#include "AddressValueNode.h" 16#include "ArrayValueNode.h" 17#include "CompoundValueNode.h" 18#include "BListTypeHandler.h" 19#include "BMessageTypeHandler.h" 20#include "CStringTypeHandler.h" 21#include "EnumerationValueNode.h" 22#include "PointerToMemberValueNode.h" 23#include "PrimitiveValueNode.h" 24#include "Type.h" 25#include "TypeHandler.h" 26 27 28static int CompareTypeHandlers(const TypeHandler* a, const TypeHandler* b, 29 void* state) 30{ 31 Type* type = (Type*)state; 32 return a->SupportsType(type) > b->SupportsType(type) ? 1 : -1; 33} 34 35 36// #pragma mark - BasicTypeHandler 37 38 39namespace { 40 41 42template<typename TypeClass, typename NodeClass> 43class BasicTypeHandler : public TypeHandler { 44public: 45 virtual const char* Name() const 46 { 47 return "Raw"; 48 } 49 50 virtual float SupportsType(Type* type) const 51 { 52 return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0; 53 } 54 55 virtual status_t CreateValueNode(ValueNodeChild* nodeChild, 56 Type* type, ValueNode*& _node) 57 { 58 TypeClass* supportedType = dynamic_cast<TypeClass*>(type); 59 if (supportedType == NULL) 60 return B_BAD_VALUE; 61 62 ValueNode* node = new(std::nothrow) NodeClass(nodeChild, supportedType); 63 if (node == NULL) 64 return B_NO_MEMORY; 65 66 _node = node; 67 return B_OK; 68 } 69}; 70 71 72} // unnamed namespace 73 74 75// #pragma mark - TypeHandlerRoster 76 77 78/*static*/ TypeHandlerRoster* TypeHandlerRoster::sDefaultInstance = NULL; 79 80 81TypeHandlerRoster::TypeHandlerRoster() 82 : 83 fLock("type handler roster") 84{ 85} 86 87 88TypeHandlerRoster::~TypeHandlerRoster() 89{ 90 for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) 91 handler->ReleaseReference(); 92} 93 94/*static*/ TypeHandlerRoster* 95TypeHandlerRoster::Default() 96{ 97 return sDefaultInstance; 98} 99 100 101/*static*/ status_t 102TypeHandlerRoster::CreateDefault() 103{ 104 if (sDefaultInstance != NULL) 105 return B_OK; 106 107 TypeHandlerRoster* roster = new(std::nothrow) TypeHandlerRoster; 108 if (roster == NULL) 109 return B_NO_MEMORY; 110 ObjectDeleter<TypeHandlerRoster> rosterDeleter(roster); 111 112 status_t error = roster->Init(); 113 if (error != B_OK) 114 return error; 115 116 error = roster->RegisterDefaultHandlers(); 117 if (error != B_OK) 118 return error; 119 120 sDefaultInstance = rosterDeleter.Detach(); 121 return B_OK; 122} 123 124 125/*static*/ void 126TypeHandlerRoster::DeleteDefault() 127{ 128 TypeHandlerRoster* roster = sDefaultInstance; 129 sDefaultInstance = NULL; 130 delete roster; 131} 132 133 134status_t 135TypeHandlerRoster::Init() 136{ 137 return fLock.InitCheck(); 138} 139 140 141status_t 142TypeHandlerRoster::RegisterDefaultHandlers() 143{ 144 TypeHandler* handler; 145 BReference<TypeHandler> handlerReference; 146 147 #undef REGISTER_BASIC_HANDLER 148 #define REGISTER_BASIC_HANDLER(name) \ 149 handler = new(std::nothrow) \ 150 BasicTypeHandler<name##Type, name##ValueNode>(); \ 151 handlerReference.SetTo(handler, true); \ 152 if (handler == NULL || !RegisterHandler(handler)) \ 153 return B_NO_MEMORY; 154 155 REGISTER_BASIC_HANDLER(Address); 156 REGISTER_BASIC_HANDLER(Array); 157 REGISTER_BASIC_HANDLER(Compound); 158 REGISTER_BASIC_HANDLER(Enumeration); 159 REGISTER_BASIC_HANDLER(PointerToMember); 160 REGISTER_BASIC_HANDLER(Primitive); 161 162 #undef REGISTER_SPECIALIZED_HANDLER 163 #define REGISTER_SPECIALIZED_HANDLER(name) \ 164 handler = new(std::nothrow) \ 165 name##TypeHandler(); \ 166 handlerReference.SetTo(handler, true); \ 167 if (handler == NULL || !RegisterHandler(handler)) \ 168 return B_NO_MEMORY; 169 170 REGISTER_SPECIALIZED_HANDLER(CString); 171 REGISTER_SPECIALIZED_HANDLER(BMessage); 172 REGISTER_SPECIALIZED_HANDLER(BList); 173 174 return B_OK; 175} 176 177 178int32 179TypeHandlerRoster::CountTypeHandlers(Type* type) 180{ 181 AutoLocker<BLocker> locker(fLock); 182 183 int32 count = 0; 184 for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) { 185 if (handler->SupportsType(type) > 0) 186 ++count; 187 } 188 189 return count; 190} 191 192 193status_t 194TypeHandlerRoster::FindBestTypeHandler(ValueNodeChild* nodeChild, Type* type, 195 TypeHandler*& _handler) 196{ 197 // find the best-supporting handler 198 AutoLocker<BLocker> locker(fLock); 199 200 TypeHandler* bestHandler = NULL; 201 float bestSupport = 0; 202 203 for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) { 204 float support = handler->SupportsType(type); 205 if (support > 0 && support > bestSupport) { 206 bestHandler = handler; 207 bestSupport = support; 208 } 209 } 210 211 if (bestHandler == NULL) 212 return B_ENTRY_NOT_FOUND; 213 214 bestHandler->AcquireReference(); 215 _handler = bestHandler; 216 return B_OK; 217} 218 219 220status_t 221TypeHandlerRoster::FindTypeHandlers(ValueNodeChild* nodeChild, Type* type, 222 TypeHandlerList*& _handlers) 223{ 224 // find the best-supporting handler 225 AutoLocker<BLocker> locker(fLock); 226 227 TypeHandlerList* handlers = new(std::nothrow) TypeHandlerList(10, false); 228 ObjectDeleter<TypeHandlerList> listDeleter(handlers); 229 if (handlers == NULL) 230 return B_NO_MEMORY; 231 232 for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) { 233 if (handler->SupportsType(type) > 0) { 234 if (!handlers->AddItem(handler)) 235 return B_NO_MEMORY; 236 } 237 } 238 239 if (handlers->CountItems() == 0) 240 return B_ENTRY_NOT_FOUND; 241 242 for (int32 i = 0; TypeHandler* handler = handlers->ItemAt(i); i++) 243 handler->AcquireReference(); 244 245 handlers->SortItems(CompareTypeHandlers, type); 246 247 _handlers = handlers; 248 listDeleter.Detach(); 249 250 return B_OK; 251} 252 253 254status_t 255TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type, 256 TypeHandler* handler, ValueNode*& _node) 257{ 258 BReference<TypeHandler> handlerReference; 259 260 // if the caller doesn't supply us with a handler to use, try to find 261 // the best match. 262 if (handler == NULL) { 263 // find the best-supporting handler 264 while (true) { 265 status_t error = FindBestTypeHandler(nodeChild, type, handler); 266 if (error == B_OK) { 267 handlerReference.SetTo(handler, true); 268 break; 269 } 270 271 // not found yet -- try to strip a modifier/typedef from the type 272 Type* nextType = type->ResolveRawType(true); 273 if (nextType == NULL || nextType == type) 274 return B_UNSUPPORTED; 275 276 type = nextType; 277 } 278 } 279 280 return handler->CreateValueNode(nodeChild, type, _node); 281} 282 283 284bool 285TypeHandlerRoster::RegisterHandler(TypeHandler* handler) 286{ 287 if (!fTypeHandlers.AddItem(handler)) 288 return false; 289 290 handler->AcquireReference(); 291 return true; 292} 293 294 295void 296TypeHandlerRoster::UnregisterHandler(TypeHandler* handler) 297{ 298 if (fTypeHandlers.RemoveItem(handler)) 299 handler->ReleaseReference(); 300} 301