1/* 2 * Copyright 2012, Rene Gollent, rene@gollent.com 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "BListValueNode.h" 8 9#include <new> 10 11#include <AutoDeleter.h> 12 13#include "AddressValueNode.h" 14#include "Architecture.h" 15#include "StringValue.h" 16#include "Tracing.h" 17#include "Type.h" 18#include "TypeLookupConstraints.h" 19#include "ValueLoader.h" 20#include "ValueLocation.h" 21#include "ValueNodeContainer.h" 22 23 24// maximum number of array elements to show by default 25static const int64 kMaxArrayElementCount = 20; 26 27 28//#pragma mark - BListValueNode::BListElementNodeChild 29 30 31class BListValueNode::BListElementNodeChild : public ValueNodeChild { 32public: 33 BListElementNodeChild(BListValueNode* parent, 34 int64 elementIndex, Type* type); 35 virtual ~BListElementNodeChild(); 36 37 virtual const BString& Name() const { return fName; }; 38 virtual Type* GetType() const { return fType; }; 39 virtual ValueNode* Parent() const { return fParent; }; 40 41 virtual status_t ResolveLocation(ValueLoader* valueLoader, 42 ValueLocation*& _location); 43 44private: 45 Type* fType; 46 BListValueNode* fParent; 47 int64 fElementIndex; 48 BString fName; 49}; 50 51 52BListValueNode::BListElementNodeChild::BListElementNodeChild( 53 BListValueNode* parent, int64 elementIndex, Type* type) 54 : 55 ValueNodeChild(), 56 fType(type), 57 fParent(parent), 58 fElementIndex(elementIndex), 59 fName() 60{ 61 fType->AcquireReference(); 62 fParent->AcquireReference(); 63 fName.SetToFormat("[%" B_PRId64 "]", fElementIndex); 64} 65 66 67BListValueNode::BListElementNodeChild::~BListElementNodeChild() 68{ 69 fType->ReleaseReference(); 70 fParent->ReleaseReference(); 71} 72 73 74status_t 75BListValueNode::BListElementNodeChild::ResolveLocation( 76 ValueLoader* valueLoader, ValueLocation*& _location) 77{ 78 uint8 addressSize = valueLoader->GetArchitecture()->AddressSize(); 79 ValueLocation* location = new(std::nothrow) ValueLocation(); 80 if (location == NULL) 81 return B_NO_MEMORY; 82 83 84 uint64 listAddress = fParent->fDataLocation.ToUInt64(); 85 listAddress += fElementIndex * addressSize; 86 87 ValuePieceLocation piece; 88 piece.SetToMemory(listAddress); 89 piece.SetSize(addressSize); 90 location->AddPiece(piece); 91 92 _location = location; 93 return B_OK; 94} 95 96 97//#pragma mark - BListItemCountNodeChild 98 99class BListValueNode::BListItemCountNodeChild : public ValueNodeChild { 100public: 101 BListItemCountNodeChild(BVariant location, 102 BListValueNode* parent, Type* type); 103 virtual ~BListItemCountNodeChild(); 104 105 virtual const BString& Name() const { return fName; }; 106 virtual Type* GetType() const { return fType; }; 107 virtual ValueNode* Parent() const { return fParent; }; 108 109 virtual status_t ResolveLocation(ValueLoader* valueLoader, 110 ValueLocation*& _location); 111 112private: 113 Type* fType; 114 BListValueNode* fParent; 115 BVariant fLocation; 116 BString fName; 117}; 118 119 120BListValueNode::BListItemCountNodeChild::BListItemCountNodeChild( 121 BVariant location, BListValueNode* parent, Type* type) 122 : 123 ValueNodeChild(), 124 fType(type), 125 fParent(parent), 126 fLocation(location), 127 fName("Capacity") 128{ 129 fType->AcquireReference(); 130 fParent->AcquireReference(); 131} 132 133 134BListValueNode::BListItemCountNodeChild::~BListItemCountNodeChild() 135{ 136 fType->ReleaseReference(); 137 fParent->ReleaseReference(); 138} 139 140 141status_t 142BListValueNode::BListItemCountNodeChild::ResolveLocation( 143 ValueLoader* valueLoader, ValueLocation*& _location) 144{ 145 ValueLocation* location = new(std::nothrow) ValueLocation(); 146 if (location == NULL) 147 return B_NO_MEMORY; 148 149 ValuePieceLocation piece; 150 piece.SetToMemory(fLocation.ToUInt64()); 151 piece.SetSize(sizeof(int32)); 152 location->AddPiece(piece); 153 154 _location = location; 155 return B_OK; 156} 157 158 159//#pragma mark - BListValueNode 160 161BListValueNode::BListValueNode(ValueNodeChild* nodeChild, 162 Type* type) 163 : 164 ValueNode(nodeChild), 165 fType(type), 166 fLoader(NULL), 167 fItemCountType(NULL), 168 fItemCount(0) 169{ 170 fType->AcquireReference(); 171} 172 173 174BListValueNode::~BListValueNode() 175{ 176 fType->ReleaseReference(); 177 for (int32 i = 0; i < fChildren.CountItems(); i++) 178 fChildren.ItemAt(i)->ReleaseReference(); 179 180 if (fItemCountType != NULL) 181 fItemCountType->ReleaseReference(); 182 183 delete fLoader; 184} 185 186 187Type* 188BListValueNode::GetType() const 189{ 190 return fType; 191} 192 193 194status_t 195BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, 196 ValueLocation*& _location, Value*& _value) 197{ 198 // get the location 199 ValueLocation* location = NodeChild()->Location(); 200 if (location == NULL) 201 return B_BAD_VALUE; 202 203 204 // get the value type 205 type_code valueType; 206 if (valueLoader->GetArchitecture()->AddressSize() == 4) { 207 valueType = B_UINT32_TYPE; 208 TRACE_LOCALS(" -> 32 bit\n"); 209 } else { 210 valueType = B_UINT64_TYPE; 211 TRACE_LOCALS(" -> 64 bit\n"); 212 } 213 214 // load the value data 215 216 status_t error = B_OK; 217 _location = location; 218 _value = NULL; 219 220 ValueLocation* memberLocation = NULL; 221 CompoundType* baseType = dynamic_cast<CompoundType*>(fType); 222 223 if (baseType->CountTemplateParameters() != 0) { 224 // for BObjectList we need to walk up 225 // the hierarchy: BObjectList -> _PointerList_ -> BList 226 if (baseType->CountBaseTypes() == 0) 227 return B_BAD_DATA; 228 229 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) 230 ->GetType()); 231 if (baseType == NULL || baseType->Name() != "_PointerList_") 232 return B_BAD_DATA; 233 234 if (baseType->CountBaseTypes() == 0) 235 return B_BAD_DATA; 236 237 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) 238 ->GetType()); 239 if (baseType == NULL || baseType->Name() != "BList") 240 return B_BAD_DATA; 241 242 } 243 244 for (int32 i = 0; i < baseType->CountDataMembers(); i++) { 245 DataMember* member = baseType->DataMemberAt(i); 246 if (strcmp(member->Name(), "fObjectList") == 0) { 247 error = baseType->ResolveDataMemberLocation(member, 248 *location, memberLocation); 249 BReference<ValueLocation> locationRef(memberLocation, true); 250 if (error != B_OK) { 251 TRACE_LOCALS( 252 "BListValueNode::ResolvedLocationAndValue(): " 253 "failed to resolve location of header member: %s\n", 254 strerror(error)); 255 return error; 256 } 257 258 error = valueLoader->LoadValue(memberLocation, valueType, 259 false, fDataLocation); 260 if (error != B_OK) 261 return error; 262 } else if (strcmp(member->Name(), "fItemCount") == 0) { 263 error = baseType->ResolveDataMemberLocation(member, 264 *location, memberLocation); 265 BReference<ValueLocation> locationRef(memberLocation, true); 266 if (error != B_OK) { 267 TRACE_LOCALS( 268 "BListValueNode::ResolvedLocationAndValue(): " 269 "failed to resolve location of header member: %s\n", 270 strerror(error)); 271 return error; 272 } 273 274 fItemCountType = member->GetType(); 275 fItemCountType->AcquireReference(); 276 277 fItemCountLocation = memberLocation->PieceAt(0).address; 278 279 BVariant listSize; 280 error = valueLoader->LoadValue(memberLocation, valueType, 281 false, listSize); 282 if (error != B_OK) 283 return error; 284 285 fItemCount = listSize.ToInt32(); 286 TRACE_LOCALS( 287 "BListValueNode::ResolvedLocationAndValue(): " 288 "detected list size %" B_PRId32 "\n", 289 fItemCount); 290 } 291 memberLocation = NULL; 292 } 293 294 if (fLoader == NULL) { 295 fLoader = new(std::nothrow)ValueLoader(*valueLoader); 296 if (fLoader == NULL) 297 return B_NO_MEMORY; 298 } 299 300 return B_OK; 301} 302 303 304status_t 305BListValueNode::CreateChildren() 306{ 307 if (fChildrenCreated) 308 return B_OK; 309 310 if (fLocationResolutionState != B_OK) 311 return fLocationResolutionState; 312 313 if (fItemCountType != NULL) { 314 BListItemCountNodeChild* countChild = new(std::nothrow) 315 BListItemCountNodeChild(fItemCountLocation, this, fItemCountType); 316 317 if (countChild == NULL) 318 return B_NO_MEMORY; 319 320 countChild->SetContainer(fContainer); 321 fChildren.AddItem(countChild); 322 } 323 324 BReference<Type> addressTypeRef; 325 Type* type = NULL; 326 CompoundType* objectType = dynamic_cast<CompoundType*>(fType); 327 if (objectType->CountTemplateParameters() != 0) { 328 AddressType* addressType = NULL; 329 status_t result = objectType->TemplateParameterAt(0)->GetType() 330 ->CreateDerivedAddressType(DERIVED_TYPE_POINTER, addressType); 331 if (result != B_OK) 332 return result; 333 334 type = addressType; 335 addressTypeRef.SetTo(type, true); 336 } else { 337 BString typeName; 338 TypeLookupConstraints constraints; 339 constraints.SetTypeKind(TYPE_ADDRESS); 340 constraints.SetBaseTypeName("void"); 341 status_t result = fLoader->LookupTypeByName(typeName, constraints, type); 342 if (result != B_OK) 343 return result; 344 } 345 346 for (int32 i = 0; i < fItemCount && i < kMaxArrayElementCount; i++) 347 { 348 BListElementNodeChild* child = 349 new(std::nothrow) BListElementNodeChild(this, i, type); 350 if (child == NULL) 351 return B_NO_MEMORY; 352 child->SetContainer(fContainer); 353 fChildren.AddItem(child); 354 } 355 356 fChildrenCreated = true; 357 358 if (fContainer != NULL) 359 fContainer->NotifyValueNodeChildrenCreated(this); 360 361 return B_OK; 362} 363 364 365int32 366BListValueNode::CountChildren() const 367{ 368 return fChildren.CountItems(); 369} 370 371 372ValueNodeChild* 373BListValueNode::ChildAt(int32 index) const 374{ 375 return fChildren.ItemAt(index); 376} 377