1 /* 2 * Copyright 2013-2015, Rene Gollent, rene@gollent.com. 3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "ArrayValueNode.h" 9 10 #include <new> 11 12 #include "Architecture.h" 13 #include "ArrayIndexPath.h" 14 #include "IntegerValue.h" 15 #include "Tracing.h" 16 #include "Type.h" 17 #include "ValueLoader.h" 18 #include "ValueLocation.h" 19 #include "ValueNodeContainer.h" 20 21 22 // maximum number of array elements to show by default 23 static const uint64 kMaxArrayElementCount = 10; 24 25 26 // #pragma mark - AbstractArrayValueNode 27 28 29 AbstractArrayValueNode::AbstractArrayValueNode(ValueNodeChild* nodeChild, 30 ArrayType* type, int32 dimension) 31 : 32 ValueNode(nodeChild), 33 fType(type), 34 fDimension(dimension), 35 fLowerBound(0), 36 fUpperBound(0), 37 fBoundsInitialized(false) 38 { 39 fType->AcquireReference(); 40 } 41 42 43 AbstractArrayValueNode::~AbstractArrayValueNode() 44 { 45 fType->ReleaseReference(); 46 47 for (int32 i = 0; AbstractArrayValueNodeChild* child = fChildren.ItemAt(i); 48 i++) { 49 child->ReleaseReference(); 50 } 51 } 52 53 54 Type* 55 AbstractArrayValueNode::GetType() const 56 { 57 return fType; 58 } 59 60 61 status_t 62 AbstractArrayValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, 63 ValueLocation*& _location, Value*& _value) 64 { 65 // get the location 66 ValueLocation* location = NodeChild()->Location(); 67 if (location == NULL) 68 return B_BAD_VALUE; 69 70 location->AcquireReference(); 71 _location = location; 72 _value = NULL; 73 return B_OK; 74 } 75 76 77 status_t 78 AbstractArrayValueNode::CreateChildren(TeamTypeInformation* info) 79 { 80 if (!fChildren.IsEmpty()) 81 return B_OK; 82 83 return CreateChildrenInRange(info, 0, kMaxArrayElementCount - 1); 84 } 85 86 87 int32 88 AbstractArrayValueNode::CountChildren() const 89 { 90 return fChildren.CountItems(); 91 } 92 93 94 ValueNodeChild* 95 AbstractArrayValueNode::ChildAt(int32 index) const 96 { 97 return fChildren.ItemAt(index); 98 } 99 100 101 bool 102 AbstractArrayValueNode::IsRangedContainer() const 103 { 104 return true; 105 } 106 107 108 void 109 AbstractArrayValueNode::ClearChildren() 110 { 111 fChildren.MakeEmpty(); 112 fLowerBound = 0; 113 fUpperBound = 0; 114 if (fContainer != NULL) 115 fContainer->NotifyValueNodeChildrenDeleted(this); 116 } 117 118 119 status_t 120 AbstractArrayValueNode::CreateChildrenInRange(TeamTypeInformation* info, 121 int32 lowIndex, int32 highIndex) 122 { 123 // TODO: ensure that we don't already have children in the specified 124 // index range. These need to be skipped if so. 125 TRACE_LOCALS("TYPE_ARRAY\n"); 126 127 int32 dimensionCount = fType->CountDimensions(); 128 bool isFinalDimension = fDimension + 1 == dimensionCount; 129 status_t error = B_OK; 130 131 if (!fBoundsInitialized) { 132 int32 lowerBound, upperBound; 133 error = SupportedChildRange(lowerBound, upperBound); 134 if (error != B_OK) 135 return error; 136 137 fLowerBound = lowerBound; 138 fUpperBound = upperBound; 139 fBoundsInitialized = true; 140 } 141 142 if (lowIndex < fLowerBound) 143 lowIndex = fLowerBound; 144 if (highIndex > fUpperBound) 145 highIndex = fUpperBound; 146 147 // create children for the array elements 148 for (int32 i = lowIndex; i <= highIndex; i++) { 149 BString name(Name()); 150 name << '[' << i << ']'; 151 if (name.Length() <= Name().Length()) 152 return B_NO_MEMORY; 153 154 AbstractArrayValueNodeChild* child; 155 if (isFinalDimension) { 156 child = new(std::nothrow) ArrayValueNodeChild(this, name, i, 157 fType->BaseType()); 158 } else { 159 child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i, 160 fType); 161 } 162 163 if (child == NULL || !fChildren.AddItem(child)) { 164 delete child; 165 return B_NO_MEMORY; 166 } 167 168 child->SetContainer(fContainer); 169 } 170 171 if (fContainer != NULL) 172 fContainer->NotifyValueNodeChildrenCreated(this); 173 174 return B_OK; 175 } 176 177 178 status_t 179 AbstractArrayValueNode::SupportedChildRange(int32& lowIndex, 180 int32& highIndex) const 181 { 182 if (!fBoundsInitialized) { 183 ArrayDimension* dimension = fType->DimensionAt(fDimension); 184 185 SubrangeType* dimensionType = dynamic_cast<SubrangeType*>( 186 dimension->GetType()); 187 188 if (dimensionType != NULL) { 189 lowIndex = dimensionType->LowerBound().ToInt32(); 190 highIndex = dimensionType->UpperBound().ToInt32(); 191 } else 192 return B_UNSUPPORTED; 193 } else { 194 lowIndex = fLowerBound; 195 highIndex = fUpperBound; 196 } 197 198 return B_OK; 199 } 200 201 202 // #pragma mark - ArrayValueNode 203 204 205 ArrayValueNode::ArrayValueNode(ValueNodeChild* nodeChild, ArrayType* type) 206 : 207 AbstractArrayValueNode(nodeChild, type, 0) 208 { 209 } 210 211 212 ArrayValueNode::~ArrayValueNode() 213 { 214 } 215 216 217 // #pragma mark - InternalArrayValueNode 218 219 220 InternalArrayValueNode::InternalArrayValueNode(ValueNodeChild* nodeChild, 221 ArrayType* type, int32 dimension) 222 : 223 AbstractArrayValueNode(nodeChild, type, dimension) 224 { 225 } 226 227 228 InternalArrayValueNode::~InternalArrayValueNode() 229 { 230 } 231 232 233 // #pragma mark - AbstractArrayValueNodeChild 234 235 236 AbstractArrayValueNodeChild::AbstractArrayValueNodeChild( 237 AbstractArrayValueNode* parent, const BString& name, int64 elementIndex) 238 : 239 fParent(parent), 240 fName(name), 241 fElementIndex(elementIndex) 242 { 243 } 244 245 246 AbstractArrayValueNodeChild::~AbstractArrayValueNodeChild() 247 { 248 } 249 250 251 const BString& 252 AbstractArrayValueNodeChild::Name() const 253 { 254 return fName; 255 } 256 257 258 ValueNode* 259 AbstractArrayValueNodeChild::Parent() const 260 { 261 return fParent; 262 } 263 264 265 // #pragma mark - ArrayValueNodeChild 266 267 268 ArrayValueNodeChild::ArrayValueNodeChild(AbstractArrayValueNode* parent, 269 const BString& name, int64 elementIndex, Type* type) 270 : 271 AbstractArrayValueNodeChild(parent, name, elementIndex), 272 fType(type) 273 { 274 fType->AcquireReference(); 275 } 276 277 278 ArrayValueNodeChild::~ArrayValueNodeChild() 279 { 280 fType->ReleaseReference(); 281 } 282 283 284 Type* 285 ArrayValueNodeChild::GetType() const 286 { 287 return fType; 288 } 289 290 291 status_t 292 ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader, 293 ValueLocation*& _location) 294 { 295 // get the parent (== array) location 296 ValueLocation* parentLocation = fParent->Location(); 297 if (parentLocation == NULL) 298 return B_BAD_VALUE; 299 300 // create an array index path 301 ArrayType* arrayType = fParent->GetArrayType(); 302 int32 dimensionCount = arrayType->CountDimensions(); 303 304 // add dummy indices first -- we'll replace them on our way back through 305 // our ancestors 306 ArrayIndexPath indexPath; 307 for (int32 i = 0; i < dimensionCount; i++) { 308 if (!indexPath.AddIndex(0)) 309 return B_NO_MEMORY; 310 } 311 312 AbstractArrayValueNodeChild* child = this; 313 for (int32 i = dimensionCount - 1; i >= 0; i--) { 314 indexPath.SetIndexAt(i, child->ElementIndex()); 315 316 child = dynamic_cast<AbstractArrayValueNodeChild*>( 317 child->ArrayParent()->NodeChild()); 318 } 319 320 // resolve the element location 321 ValueLocation* location; 322 status_t error = arrayType->ResolveElementLocation(indexPath, 323 *parentLocation, location); 324 if (error != B_OK) { 325 TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): " 326 "ResolveElementLocation() failed: %s\n", strerror(error)); 327 return error; 328 } 329 330 _location = location; 331 return B_OK; 332 } 333 334 335 // #pragma mark - InternalArrayValueNodeChild 336 337 338 InternalArrayValueNodeChild::InternalArrayValueNodeChild( 339 AbstractArrayValueNode* parent, const BString& name, int64 elementIndex, 340 ArrayType* type) 341 : 342 AbstractArrayValueNodeChild(parent, name, elementIndex), 343 fType(type) 344 { 345 fType->AcquireReference(); 346 } 347 348 349 InternalArrayValueNodeChild::~InternalArrayValueNodeChild() 350 { 351 fType->ReleaseReference(); 352 } 353 354 355 Type* 356 InternalArrayValueNodeChild::GetType() const 357 { 358 return fType; 359 } 360 361 362 bool 363 InternalArrayValueNodeChild::IsInternal() const 364 { 365 return true; 366 } 367 368 369 status_t 370 InternalArrayValueNodeChild::CreateInternalNode(ValueNode*& _node) 371 { 372 ValueNode* node = new(std::nothrow) InternalArrayValueNode(this, fType, 373 fParent->Dimension() + 1); 374 if (node == NULL) 375 return B_NO_MEMORY; 376 377 _node = node; 378 return B_OK; 379 } 380 381 382 status_t 383 InternalArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader, 384 ValueLocation*& _location) 385 { 386 // This is an internal child node for a non-final dimension -- just clone 387 // the parent's location. 388 ValueLocation* parentLocation = fParent->Location(); 389 if (parentLocation == NULL) 390 return B_BAD_VALUE; 391 392 parentLocation->AcquireReference(); 393 _location = parentLocation; 394 395 return B_OK; 396 } 397