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