1 /* 2 * Copyright 2011-2015, Rene Gollent, rene@gollent.com 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "BMessageValueNode.h" 8 9 #include <new> 10 11 #include <AutoDeleter.h> 12 #include <MessageAdapter.h> 13 #include <MessagePrivate.h> 14 15 #include "Architecture.h" 16 #include "StringValue.h" 17 #include "TeamTypeInformation.h" 18 #include "Tracing.h" 19 #include "Type.h" 20 #include "TypeLookupConstraints.h" 21 #include "ValueLoader.h" 22 #include "ValueLocation.h" 23 #include "ValueNodeContainer.h" 24 25 26 static const int64 kMaxStringSize = 64; 27 28 29 // #pragma mark - BMessageWhatNodeChild 30 31 32 class BMessageWhatNodeChild : public ValueNodeChild { 33 public: 34 BMessageWhatNodeChild(BMessageValueNode* parent, DataMember* member, 35 Type* type) 36 : 37 ValueNodeChild(), 38 fMember(member), 39 fName("what"), 40 fParent(parent), 41 fType(type) 42 { 43 fParent->AcquireReference(); 44 fType->AcquireReference(); 45 } 46 47 virtual ~BMessageWhatNodeChild() 48 { 49 fParent->ReleaseReference(); 50 fType->ReleaseReference(); 51 } 52 53 virtual const BString& Name() const 54 { 55 return fName; 56 } 57 58 virtual Type* GetType() const 59 { 60 return fType; 61 } 62 63 virtual ValueNode* Parent() const 64 { 65 return fParent; 66 } 67 68 virtual status_t ResolveLocation(ValueLoader* valueLoader, 69 ValueLocation*& _location) 70 { 71 ValueLocation* parentLocation = fParent->Location(); 72 ValueLocation* location; 73 CompoundType* type = dynamic_cast<CompoundType*>(fParent->GetType()); 74 status_t error = B_OK; 75 if (fParent->fIsFlatMessage) { 76 location = new ValueLocation(); 77 if (location == NULL) 78 return B_NO_MEMORY; 79 80 ValuePieceLocation piece; 81 piece.SetToMemory(parentLocation->PieceAt(0).address 82 + sizeof(uint32)); 83 piece.SetSize(sizeof(uint32)); 84 location->AddPiece(piece); 85 } else { 86 error = type->ResolveDataMemberLocation(fMember, 87 *parentLocation, location); 88 } 89 90 if (error != B_OK) 91 return error; 92 93 _location = location; 94 return B_OK; 95 } 96 97 private: 98 DataMember* fMember; 99 BString fName; 100 BMessageValueNode* fParent; 101 Type* fType; 102 }; 103 104 105 // #pragma mark - BMessageValueNode 106 107 108 BMessageValueNode::BMessageValueNode(ValueNodeChild* nodeChild, 109 Type* type) 110 : 111 ValueNode(nodeChild), 112 fType(type), 113 fHeader(NULL), 114 fFields(NULL), 115 fData(NULL), 116 fIsFlatMessage(false) 117 { 118 fType->AcquireReference(); 119 } 120 121 122 BMessageValueNode::~BMessageValueNode() 123 { 124 fType->ReleaseReference(); 125 for (int32 i = 0; i < fChildren.CountItems(); i++) 126 fChildren.ItemAt(i)->ReleaseReference(); 127 128 delete fHeader; 129 delete[] fFields; 130 delete[] fData; 131 } 132 133 134 Type* 135 BMessageValueNode::GetType() const 136 { 137 return fType; 138 } 139 140 141 status_t 142 BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, 143 ValueLocation*& _location, Value*& _value) 144 { 145 fIsFlatMessage = dynamic_cast<BMessageFieldNodeChild*>(NodeChild()) 146 != NULL; 147 148 // get the location 149 ValueLocation* location = NodeChild()->Location(); 150 if (location == NULL) 151 return B_BAD_VALUE; 152 153 154 // get the value type 155 type_code valueType; 156 if (valueLoader->GetArchitecture()->AddressSize() == 4) { 157 valueType = B_UINT32_TYPE; 158 TRACE_LOCALS(" -> 32 bit\n"); 159 } else { 160 valueType = B_UINT64_TYPE; 161 TRACE_LOCALS(" -> 64 bit\n"); 162 } 163 164 // load the value data 165 166 status_t error = B_OK; 167 ValueLocation* memberLocation = NULL; 168 169 BVariant headerAddress; 170 BVariant fieldAddress; 171 BVariant what; 172 173 CompoundType* baseType = dynamic_cast<CompoundType*>(fType); 174 175 if (fIsFlatMessage) { 176 headerAddress.SetTo(location->PieceAt(0).address); 177 fieldAddress.SetTo(headerAddress.ToUInt64() 178 + sizeof(BMessage::message_header)); 179 } else { 180 for (int32 i = 0; i < baseType->CountDataMembers(); i++) { 181 DataMember* member = baseType->DataMemberAt(i); 182 if (strcmp(member->Name(), "fHeader") == 0) { 183 error = baseType->ResolveDataMemberLocation(member, 184 *location, memberLocation); 185 BReference<ValueLocation> locationRef(memberLocation, true); 186 if (error != B_OK) { 187 TRACE_LOCALS( 188 "BMessageValueNode::ResolvedLocationAndValue(): " 189 "failed to resolve location of header member: %s\n", 190 strerror(error)); 191 return error; 192 } 193 194 error = valueLoader->LoadValue(memberLocation, valueType, 195 false, headerAddress); 196 if (error != B_OK) 197 return error; 198 } else if (strcmp(member->Name(), "what") == 0) { 199 error = baseType->ResolveDataMemberLocation(member, 200 *location, memberLocation); 201 BReference<ValueLocation> locationRef(memberLocation, true); 202 if (error != B_OK) { 203 TRACE_LOCALS( 204 "BMessageValueNode::ResolvedLocationAndValue(): " 205 "failed to resolve location of header member: %s\n", 206 strerror(error)); 207 return error; 208 } 209 error = valueLoader->LoadValue(memberLocation, B_UINT32_TYPE, 210 false, what); 211 if (error != B_OK) 212 return error; 213 } else if (strcmp(member->Name(), "fFields") == 0) { 214 error = baseType->ResolveDataMemberLocation(member, 215 *location, memberLocation); 216 BReference<ValueLocation> locationRef(memberLocation, true); 217 if (error != B_OK) { 218 TRACE_LOCALS( 219 "BMessageValueNode::ResolvedLocationAndValue(): " 220 "failed to resolve location of field member: %s\n", 221 strerror(error)); 222 return error; 223 } 224 error = valueLoader->LoadValue(memberLocation, valueType, 225 false, fieldAddress); 226 if (error != B_OK) 227 return error; 228 } else if (strcmp(member->Name(), "fData") == 0) { 229 error = baseType->ResolveDataMemberLocation(member, 230 *location, memberLocation); 231 BReference<ValueLocation> locationRef(memberLocation, true); 232 if (error != B_OK) { 233 TRACE_LOCALS( 234 "BMessageValueNode::ResolvedLocationAndValue(): " 235 "failed to resolve location of data member: %s\n", 236 strerror(error)); 237 return error; 238 } 239 error = valueLoader->LoadValue(memberLocation, valueType, 240 false, fDataLocation); 241 if (error != B_OK) 242 return error; 243 } 244 memberLocation = NULL; 245 } 246 } 247 248 fHeader = new(std::nothrow) BMessage::message_header(); 249 if (fHeader == NULL) 250 return B_NO_MEMORY; 251 error = valueLoader->LoadRawValue(headerAddress, sizeof( 252 BMessage::message_header), fHeader); 253 TRACE_LOCALS("BMessage: Header Address: 0x%" B_PRIx64 ", result: %s\n", 254 headerAddress.ToUInt64(), strerror(error)); 255 if (error != B_OK) 256 return error; 257 258 if (fHeader->format != MESSAGE_FORMAT_HAIKU 259 || (fHeader->flags & MESSAGE_FLAG_VALID) == 0) 260 return B_NOT_A_MESSAGE; 261 262 if (fIsFlatMessage) 263 what.SetTo(fHeader->what); 264 else 265 fHeader->what = what.ToUInt32(); 266 267 TRACE_LOCALS("BMessage: what: 0x%" B_PRIx32 ", result: %s\n", 268 what.ToUInt32(), strerror(error)); 269 270 size_t fieldsSize = fHeader->field_count * sizeof( 271 BMessage::field_header); 272 if (fIsFlatMessage) 273 fDataLocation.SetTo(fieldAddress.ToUInt64() + fieldsSize); 274 275 size_t totalSize = sizeof(BMessage::message_header) + fieldsSize 276 + fHeader->data_size; 277 uint8* messageBuffer = new(std::nothrow) uint8[totalSize]; 278 if (messageBuffer == NULL) 279 return B_NO_MEMORY; 280 281 ArrayDeleter<uint8> deleter(messageBuffer); 282 283 memset(messageBuffer, 0, totalSize); 284 memcpy(messageBuffer, fHeader, sizeof(BMessage::message_header)); 285 uint8* tempBuffer = messageBuffer + sizeof(BMessage::message_header); 286 if (fieldsSize > 0) { 287 fFields = new(std::nothrow) 288 BMessage::field_header[fHeader->field_count]; 289 if (fFields == NULL) 290 return B_NO_MEMORY; 291 292 error = valueLoader->LoadRawValue(fieldAddress, fieldsSize, 293 fFields); 294 TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64 295 ", result: %s\n", headerAddress.ToUInt64(), strerror(error)); 296 if (error != B_OK) 297 return error; 298 299 fData = new(std::nothrow) uint8[fHeader->data_size]; 300 if (fData == NULL) 301 return B_NO_MEMORY; 302 303 error = valueLoader->LoadRawValue(fDataLocation, fHeader->data_size, 304 fData); 305 TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64 306 ", result: %s\n", fDataLocation.ToUInt64(), strerror(error)); 307 if (error != B_OK) 308 return error; 309 memcpy(tempBuffer, fFields, fieldsSize); 310 tempBuffer += fieldsSize; 311 memcpy(tempBuffer, fData, fHeader->data_size); 312 } 313 314 error = fMessage.Unflatten((const char*)messageBuffer); 315 if (error != B_OK) 316 return error; 317 318 location->AcquireReference(); 319 _location = location; 320 _value = NULL; 321 322 return B_OK; 323 } 324 325 326 status_t 327 BMessageValueNode::CreateChildren(TeamTypeInformation* info) 328 { 329 DataMember* member = NULL; 330 CompoundType* messageType = dynamic_cast<CompoundType*>(fType); 331 for (int32 i = 0; i < messageType->CountDataMembers(); i++) { 332 member = messageType->DataMemberAt(i); 333 if (strcmp(member->Name(), "what") == 0) { 334 ValueNodeChild* whatNode 335 = new(std::nothrow) BMessageWhatNodeChild(this, member, 336 member->GetType()); 337 if (whatNode == NULL) 338 return B_NO_MEMORY; 339 340 whatNode->SetContainer(fContainer); 341 fChildren.AddItem(whatNode); 342 break; 343 } 344 } 345 346 char* name; 347 type_code type; 348 int32 count; 349 Type* fieldType = NULL; 350 BReference<Type> typeRef; 351 for (int32 i = 0; fMessage.GetInfo(B_ANY_TYPE, i, &name, &type, 352 &count) == B_OK; i++) { 353 fieldType = NULL; 354 355 _GetTypeForTypeCode(info, type, fieldType); 356 if (fieldType != NULL) 357 typeRef.SetTo(fieldType, true); 358 359 BMessageFieldNodeChild* node = new(std::nothrow) 360 BMessageFieldNodeChild(this, 361 fieldType != NULL ? fieldType : fType, name, type, 362 count); 363 if (node == NULL) 364 return B_NO_MEMORY; 365 366 node->SetContainer(fContainer); 367 fChildren.AddItem(node); 368 } 369 370 fChildrenCreated = true; 371 372 if (fContainer != NULL) 373 fContainer->NotifyValueNodeChildrenCreated(this); 374 375 return B_OK; 376 } 377 378 379 int32 380 BMessageValueNode::CountChildren() const 381 { 382 return fChildren.CountItems(); 383 } 384 385 386 ValueNodeChild* 387 BMessageValueNode::ChildAt(int32 index) const 388 { 389 return fChildren.ItemAt(index); 390 } 391 392 393 status_t 394 BMessageValueNode::_GetTypeForTypeCode(TeamTypeInformation* info, 395 type_code type, Type*& _type) 396 { 397 BString typeName; 398 TypeLookupConstraints constraints; 399 400 switch(type) { 401 case B_BOOL_TYPE: 402 typeName = "bool"; 403 constraints.SetTypeKind(TYPE_PRIMITIVE); 404 break; 405 406 case B_INT8_TYPE: 407 typeName = "int8"; 408 constraints.SetTypeKind(TYPE_TYPEDEF); 409 break; 410 411 case B_UINT8_TYPE: 412 typeName = "uint8"; 413 constraints.SetTypeKind(TYPE_TYPEDEF); 414 break; 415 416 case B_INT16_TYPE: 417 typeName = "int16"; 418 constraints.SetTypeKind(TYPE_TYPEDEF); 419 break; 420 421 case B_UINT16_TYPE: 422 typeName = "uint16"; 423 constraints.SetTypeKind(TYPE_TYPEDEF); 424 break; 425 426 case B_INT32_TYPE: 427 typeName = "int32"; 428 constraints.SetTypeKind(TYPE_TYPEDEF); 429 break; 430 431 case B_UINT32_TYPE: 432 typeName = "uint32"; 433 constraints.SetTypeKind(TYPE_TYPEDEF); 434 break; 435 436 case B_INT64_TYPE: 437 typeName = "int64"; 438 constraints.SetTypeKind(TYPE_TYPEDEF); 439 break; 440 441 case B_UINT64_TYPE: 442 typeName = "uint64"; 443 constraints.SetTypeKind(TYPE_TYPEDEF); 444 break; 445 446 case B_FLOAT_TYPE: 447 typeName = "float"; 448 constraints.SetTypeKind(TYPE_PRIMITIVE); 449 break; 450 451 case B_DOUBLE_TYPE: 452 typeName = "double"; 453 constraints.SetTypeKind(TYPE_PRIMITIVE); 454 break; 455 456 case B_MESSAGE_TYPE: 457 typeName = "BMessage"; 458 constraints.SetTypeKind(TYPE_COMPOUND); 459 break; 460 461 case B_MESSENGER_TYPE: 462 typeName = "BMessenger"; 463 constraints.SetTypeKind(TYPE_COMPOUND); 464 break; 465 466 case B_POINT_TYPE: 467 typeName = "BPoint"; 468 constraints.SetTypeKind(TYPE_COMPOUND); 469 break; 470 471 case B_RECT_TYPE: 472 typeName = "BRect"; 473 constraints.SetTypeKind(TYPE_COMPOUND); 474 break; 475 476 case B_REF_TYPE: 477 typeName = "entry_ref"; 478 constraints.SetTypeKind(TYPE_COMPOUND); 479 break; 480 481 case B_RGB_COLOR_TYPE: 482 typeName = "rgb_color"; 483 constraints.SetTypeKind(TYPE_COMPOUND); 484 break; 485 486 case B_STRING_TYPE: 487 { 488 typeName = "char"; 489 constraints.SetTypeKind(TYPE_PRIMITIVE); 490 Type* baseType = NULL; 491 status_t result = info->LookupTypeByName(typeName, constraints, 492 baseType); 493 if (result != B_OK) 494 return result; 495 BReference<Type> typeReference(baseType, true); 496 ArrayType* arrayType; 497 result = baseType->CreateDerivedArrayType(0, kMaxStringSize, true, 498 arrayType); 499 if (result == B_OK) 500 _type = arrayType; 501 502 return result; 503 break; 504 } 505 506 case B_POINTER_TYPE: 507 default: 508 typeName = "void*"; 509 constraints.SetTypeKind(TYPE_ADDRESS); 510 break; 511 } 512 513 return info->LookupTypeByName(typeName, constraints, _type); 514 } 515 516 517 status_t 518 BMessageValueNode::_FindField(const char* name, type_code type, 519 BMessage::field_header** result) const 520 { 521 if (name == NULL) 522 return B_BAD_VALUE; 523 524 if (fHeader == NULL) 525 return B_NO_INIT; 526 527 if (fHeader->field_count == 0 || fFields == NULL || fData == NULL) 528 return B_NAME_NOT_FOUND; 529 530 uint32 hash = _HashName(name) % fHeader->hash_table_size; 531 int32 nextField = fHeader->hash_table[hash]; 532 533 while (nextField >= 0) { 534 BMessage::field_header* field = &fFields[nextField]; 535 if ((field->flags & FIELD_FLAG_VALID) == 0) 536 break; 537 538 if (strncmp((const char*)(fData + field->offset), name, 539 field->name_length) == 0) { 540 if (type != B_ANY_TYPE && field->type != type) 541 return B_BAD_TYPE; 542 543 *result = field; 544 return B_OK; 545 } 546 547 nextField = field->next_field; 548 } 549 550 return B_NAME_NOT_FOUND; 551 } 552 553 554 uint32 555 BMessageValueNode::_HashName(const char* name) const 556 { 557 char ch; 558 uint32 result = 0; 559 560 while ((ch = *name++) != 0) { 561 result = (result << 7) ^ (result >> 24); 562 result ^= ch; 563 } 564 565 result ^= result << 12; 566 return result; 567 } 568 569 570 status_t 571 BMessageValueNode::_FindDataLocation(const char* name, type_code type, 572 int32 index, ValueLocation& location) const 573 { 574 BMessage::field_header* field = NULL; 575 int32 offset = 0; 576 int32 size = 0; 577 status_t result = _FindField(name, type, &field); 578 if (result != B_OK) 579 return result; 580 581 if (index < 0 || (uint32)index >= field->count) 582 return B_BAD_INDEX; 583 584 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 585 size = field->data_size / field->count; 586 offset = field->offset + field->name_length + index * size; 587 } else { 588 offset = field->offset + field->name_length; 589 uint8 *pointer = fData + field->offset + field->name_length; 590 for (int32 i = 0; i < index; i++) { 591 pointer += *(uint32*)pointer + sizeof(uint32); 592 offset += *(uint32*)pointer + sizeof(uint32); 593 } 594 595 size = *(uint32*)pointer; 596 offset += sizeof(uint32); 597 } 598 599 ValuePieceLocation piece; 600 piece.SetToMemory(fDataLocation.ToUInt64() + offset); 601 piece.SetSize(size); 602 location.Clear(); 603 location.AddPiece(piece); 604 605 return B_OK; 606 } 607 608 609 // #pragma mark - BMessageValueNode::BMessageFieldNode 610 611 612 BMessageValueNode::BMessageFieldNode::BMessageFieldNode( 613 BMessageFieldNodeChild *child, BMessageValueNode* parent, 614 const BString &name, type_code type, int32 count) 615 : 616 ValueNode(child), 617 fName(name), 618 fType(parent->GetType()), 619 fParent(parent), 620 fFieldType(type), 621 fFieldCount(count) 622 { 623 fParent->AcquireReference(); 624 fType->AcquireReference(); 625 } 626 627 628 BMessageValueNode::BMessageFieldNode::~BMessageFieldNode() 629 { 630 fParent->ReleaseReference(); 631 fType->ReleaseReference(); 632 } 633 634 635 Type* 636 BMessageValueNode::BMessageFieldNode::GetType() const 637 { 638 return fType; 639 } 640 641 642 status_t 643 BMessageValueNode::BMessageFieldNode::CreateChildren(TeamTypeInformation* info) 644 { 645 Type* type = NULL; 646 status_t error = fParent->_GetTypeForTypeCode(info, fFieldType, type); 647 if (error != B_OK) 648 return error; 649 650 BReference<Type> typeRef(type, true); 651 for (int32 i = 0; i < fFieldCount; i++) { 652 BMessageFieldNodeChild* child = new(std::nothrow) 653 BMessageFieldNodeChild(fParent, type, fName, fFieldType, 654 fFieldCount, i); 655 656 if (child == NULL) 657 return B_NO_MEMORY; 658 659 if (fContainer != NULL) 660 child->SetContainer(fContainer); 661 662 fChildren.AddItem(child); 663 } 664 665 fChildrenCreated = true; 666 667 if (fContainer != NULL) 668 fContainer->NotifyValueNodeChildrenCreated(this); 669 670 return B_OK; 671 } 672 673 674 int32 675 BMessageValueNode::BMessageFieldNode::CountChildren() const 676 { 677 return fChildren.CountItems(); 678 } 679 680 ValueNodeChild* 681 BMessageValueNode::BMessageFieldNode::ChildAt(int32 index) const 682 { 683 return fChildren.ItemAt(index); 684 } 685 686 687 status_t 688 BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue( 689 ValueLoader* loader, ValueLocation *& _location, Value*& _value) 690 { 691 _location = NULL; 692 _value = NULL; 693 694 return B_OK; 695 } 696 697 698 // #pragma mark - BMessageValueNode::BMessageFieldNodeChild 699 700 701 BMessageValueNode::BMessageFieldNodeChild::BMessageFieldNodeChild( 702 BMessageValueNode* parent, Type* nodeType, const BString &name, 703 type_code type, int32 count, int32 index) 704 : 705 ValueNodeChild(), 706 fName(name), 707 fPresentationName(name), 708 fType(nodeType), 709 fParent(parent), 710 fFieldType(type), 711 fFieldCount(count), 712 fFieldIndex(index) 713 { 714 fParent->AcquireReference(); 715 fType->AcquireReference(); 716 717 if (fFieldIndex >= 0) 718 fPresentationName.SetToFormat("[%" B_PRId32 "]", fFieldIndex); 719 } 720 721 722 BMessageValueNode::BMessageFieldNodeChild::~BMessageFieldNodeChild() 723 { 724 fParent->ReleaseReference(); 725 fType->ReleaseReference(); 726 } 727 728 729 const BString& 730 BMessageValueNode::BMessageFieldNodeChild::Name() const 731 { 732 return fPresentationName; 733 } 734 735 736 Type* 737 BMessageValueNode::BMessageFieldNodeChild::GetType() const 738 { 739 return fType; 740 } 741 742 743 ValueNode* 744 BMessageValueNode::BMessageFieldNodeChild::Parent() const 745 { 746 return fParent; 747 } 748 749 750 bool 751 BMessageValueNode::BMessageFieldNodeChild::IsInternal() const 752 { 753 return fFieldCount > 1 && fFieldIndex == -1; 754 } 755 756 757 status_t 758 BMessageValueNode::BMessageFieldNodeChild::CreateInternalNode( 759 ValueNode*& _node) 760 { 761 BMessageFieldNode* node = new(std::nothrow) 762 BMessageFieldNode(this, fParent, fName, fFieldType, fFieldCount); 763 if (node == NULL) 764 return B_NO_MEMORY; 765 766 _node = node; 767 return B_OK; 768 } 769 770 771 status_t 772 BMessageValueNode::BMessageFieldNodeChild::ResolveLocation( 773 ValueLoader* valueLoader, ValueLocation*& _location) 774 { 775 _location = new(std::nothrow)ValueLocation(); 776 777 if (_location == NULL) 778 return B_NO_MEMORY; 779 780 return fParent->_FindDataLocation(fName, fFieldType, fFieldIndex >= 0 781 ? fFieldIndex : 0, *_location); 782 } 783 784 785