2 * Copyright 2011-2015, Rene Gollent, rene@gollent.com
3 * Distributed under the terms of the MIT License.
7 #include "BMessageValueNode.h"
11 #include <AutoDeleter.h>
12 #include <MessageAdapter.h>
13 #include <MessagePrivate.h>
15 #include "Architecture.h"
16 #include "StringValue.h"
17 #include "TeamTypeInformation.h"
20 #include "TypeLookupConstraints.h"
21 #include "ValueLoader.h"
22 #include "ValueLocation.h"
23 #include "ValueNodeContainer.h"
26 static const int64 kMaxStringSize
= 64;
29 // #pragma mark - BMessageWhatNodeChild
32 class BMessageWhatNodeChild
: public ValueNodeChild
{
34 BMessageWhatNodeChild(BMessageValueNode
* parent
, DataMember
* member
,
43 fParent
->AcquireReference();
44 fType
->AcquireReference();
47 virtual ~BMessageWhatNodeChild()
49 fParent
->ReleaseReference();
50 fType
->ReleaseReference();
53 virtual const BString
& Name() const
58 virtual Type
* GetType() const
63 virtual ValueNode
* Parent() const
68 virtual status_t
ResolveLocation(ValueLoader
* valueLoader
,
69 ValueLocation
*& _location
)
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();
80 ValuePieceLocation piece
;
81 piece
.SetToMemory(parentLocation
->PieceAt(0).address
83 piece
.SetSize(sizeof(uint32
));
84 location
->AddPiece(piece
);
86 error
= type
->ResolveDataMemberLocation(fMember
,
87 *parentLocation
, location
);
100 BMessageValueNode
* fParent
;
105 // #pragma mark - BMessageValueNode
108 BMessageValueNode::BMessageValueNode(ValueNodeChild
* nodeChild
,
111 ValueNode(nodeChild
),
116 fIsFlatMessage(false)
118 fType
->AcquireReference();
122 BMessageValueNode::~BMessageValueNode()
124 fType
->ReleaseReference();
125 for (int32 i
= 0; i
< fChildren
.CountItems(); i
++)
126 fChildren
.ItemAt(i
)->ReleaseReference();
135 BMessageValueNode::GetType() const
142 BMessageValueNode::ResolvedLocationAndValue(ValueLoader
* valueLoader
,
143 ValueLocation
*& _location
, Value
*& _value
)
145 fIsFlatMessage
= dynamic_cast<BMessageFieldNodeChild
*>(NodeChild())
149 ValueLocation
* location
= NodeChild()->Location();
150 if (location
== NULL
)
154 // get the value type
156 if (valueLoader
->GetArchitecture()->AddressSize() == 4) {
157 valueType
= B_UINT32_TYPE
;
158 TRACE_LOCALS(" -> 32 bit\n");
160 valueType
= B_UINT64_TYPE
;
161 TRACE_LOCALS(" -> 64 bit\n");
164 // load the value data
166 status_t error
= B_OK
;
167 _location
= location
;
170 ValueLocation
* memberLocation
= NULL
;
172 BVariant headerAddress
;
173 BVariant fieldAddress
;
176 CompoundType
* baseType
= dynamic_cast<CompoundType
*>(fType
);
178 if (fIsFlatMessage
) {
179 headerAddress
.SetTo(location
->PieceAt(0).address
);
180 fieldAddress
.SetTo(headerAddress
.ToUInt64()
181 + sizeof(BMessage::message_header
));
183 for (int32 i
= 0; i
< baseType
->CountDataMembers(); i
++) {
184 DataMember
* member
= baseType
->DataMemberAt(i
);
185 if (strcmp(member
->Name(), "fHeader") == 0) {
186 error
= baseType
->ResolveDataMemberLocation(member
,
187 *location
, memberLocation
);
188 BReference
<ValueLocation
> locationRef(memberLocation
, true);
191 "BMessageValueNode::ResolvedLocationAndValue(): "
192 "failed to resolve location of header member: %s\n",
197 error
= valueLoader
->LoadValue(memberLocation
, valueType
,
198 false, headerAddress
);
201 } else if (strcmp(member
->Name(), "what") == 0) {
202 error
= baseType
->ResolveDataMemberLocation(member
,
203 *location
, memberLocation
);
204 BReference
<ValueLocation
> locationRef(memberLocation
, true);
207 "BMessageValueNode::ResolvedLocationAndValue(): "
208 "failed to resolve location of header member: %s\n",
212 error
= valueLoader
->LoadValue(memberLocation
, B_UINT32_TYPE
,
216 } else if (strcmp(member
->Name(), "fFields") == 0) {
217 error
= baseType
->ResolveDataMemberLocation(member
,
218 *location
, memberLocation
);
219 BReference
<ValueLocation
> locationRef(memberLocation
, true);
222 "BMessageValueNode::ResolvedLocationAndValue(): "
223 "failed to resolve location of field member: %s\n",
227 error
= valueLoader
->LoadValue(memberLocation
, valueType
,
228 false, fieldAddress
);
231 } else if (strcmp(member
->Name(), "fData") == 0) {
232 error
= baseType
->ResolveDataMemberLocation(member
,
233 *location
, memberLocation
);
234 BReference
<ValueLocation
> locationRef(memberLocation
, true);
237 "BMessageValueNode::ResolvedLocationAndValue(): "
238 "failed to resolve location of data member: %s\n",
242 error
= valueLoader
->LoadValue(memberLocation
, valueType
,
243 false, fDataLocation
);
247 memberLocation
= NULL
;
251 fHeader
= new(std::nothrow
) BMessage::message_header();
254 error
= valueLoader
->LoadRawValue(headerAddress
, sizeof(
255 BMessage::message_header
), fHeader
);
256 TRACE_LOCALS("BMessage: Header Address: 0x%" B_PRIx64
", result: %s\n",
257 headerAddress
.ToUInt64(), strerror(error
));
261 if (fHeader
->format
!= MESSAGE_FORMAT_HAIKU
262 || (fHeader
->flags
& MESSAGE_FLAG_VALID
) == 0)
263 return B_NOT_A_MESSAGE
;
266 what
.SetTo(fHeader
->what
);
268 fHeader
->what
= what
.ToUInt32();
270 TRACE_LOCALS("BMessage: what: 0x%" B_PRIx32
", result: %s\n",
271 what
.ToUInt32(), strerror(error
));
273 size_t fieldsSize
= fHeader
->field_count
* sizeof(
274 BMessage::field_header
);
276 fDataLocation
.SetTo(fieldAddress
.ToUInt64() + fieldsSize
);
278 size_t totalSize
= sizeof(BMessage::message_header
) + fieldsSize
279 + fHeader
->data_size
;
280 uint8
* messageBuffer
= new(std::nothrow
) uint8
[totalSize
];
281 if (messageBuffer
== NULL
)
284 ArrayDeleter
<uint8
> deleter(messageBuffer
);
286 memset(messageBuffer
, 0, totalSize
);
287 memcpy(messageBuffer
, fHeader
, sizeof(BMessage::message_header
));
288 uint8
* tempBuffer
= messageBuffer
+ sizeof(BMessage::message_header
);
289 if (fieldsSize
> 0) {
290 fFields
= new(std::nothrow
)
291 BMessage::field_header
[fHeader
->field_count
];
295 error
= valueLoader
->LoadRawValue(fieldAddress
, fieldsSize
,
297 TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64
298 ", result: %s\n", headerAddress
.ToUInt64(), strerror(error
));
302 fData
= new(std::nothrow
) uint8
[fHeader
->data_size
];
306 error
= valueLoader
->LoadRawValue(fDataLocation
, fHeader
->data_size
,
308 TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64
309 ", result: %s\n", fDataLocation
.ToUInt64(), strerror(error
));
312 memcpy(tempBuffer
, fFields
, fieldsSize
);
313 tempBuffer
+= fieldsSize
;
314 memcpy(tempBuffer
, fData
, fHeader
->data_size
);
317 error
= fMessage
.Unflatten((const char*)messageBuffer
);
326 BMessageValueNode::CreateChildren(TeamTypeInformation
* info
)
328 DataMember
* member
= NULL
;
329 CompoundType
* messageType
= dynamic_cast<CompoundType
*>(fType
);
330 for (int32 i
= 0; i
< messageType
->CountDataMembers(); i
++) {
331 member
= messageType
->DataMemberAt(i
);
332 if (strcmp(member
->Name(), "what") == 0) {
333 ValueNodeChild
* whatNode
334 = new(std::nothrow
) BMessageWhatNodeChild(this, member
,
336 if (whatNode
== NULL
)
339 whatNode
->SetContainer(fContainer
);
340 fChildren
.AddItem(whatNode
);
348 Type
* fieldType
= NULL
;
349 BReference
<Type
> typeRef
;
350 for (int32 i
= 0; fMessage
.GetInfo(B_ANY_TYPE
, i
, &name
, &type
,
351 &count
) == B_OK
; i
++) {
354 _GetTypeForTypeCode(info
, type
, fieldType
);
355 if (fieldType
!= NULL
)
356 typeRef
.SetTo(fieldType
, true);
358 BMessageFieldNodeChild
* node
= new(std::nothrow
)
359 BMessageFieldNodeChild(this,
360 fieldType
!= NULL
? fieldType
: fType
, name
, type
,
365 node
->SetContainer(fContainer
);
366 fChildren
.AddItem(node
);
369 fChildrenCreated
= true;
371 if (fContainer
!= NULL
)
372 fContainer
->NotifyValueNodeChildrenCreated(this);
379 BMessageValueNode::CountChildren() const
381 return fChildren
.CountItems();
386 BMessageValueNode::ChildAt(int32 index
) const
388 return fChildren
.ItemAt(index
);
393 BMessageValueNode::_GetTypeForTypeCode(TeamTypeInformation
* info
,
394 type_code type
, Type
*& _type
)
397 TypeLookupConstraints constraints
;
402 constraints
.SetTypeKind(TYPE_PRIMITIVE
);
407 constraints
.SetTypeKind(TYPE_TYPEDEF
);
412 constraints
.SetTypeKind(TYPE_TYPEDEF
);
417 constraints
.SetTypeKind(TYPE_TYPEDEF
);
422 constraints
.SetTypeKind(TYPE_TYPEDEF
);
427 constraints
.SetTypeKind(TYPE_TYPEDEF
);
432 constraints
.SetTypeKind(TYPE_TYPEDEF
);
437 constraints
.SetTypeKind(TYPE_TYPEDEF
);
442 constraints
.SetTypeKind(TYPE_TYPEDEF
);
447 constraints
.SetTypeKind(TYPE_PRIMITIVE
);
452 constraints
.SetTypeKind(TYPE_PRIMITIVE
);
456 typeName
= "BMessage";
457 constraints
.SetTypeKind(TYPE_COMPOUND
);
460 case B_MESSENGER_TYPE
:
461 typeName
= "BMessenger";
462 constraints
.SetTypeKind(TYPE_COMPOUND
);
467 constraints
.SetTypeKind(TYPE_COMPOUND
);
472 constraints
.SetTypeKind(TYPE_COMPOUND
);
476 typeName
= "entry_ref";
477 constraints
.SetTypeKind(TYPE_COMPOUND
);
480 case B_RGB_COLOR_TYPE
:
481 typeName
= "rgb_color";
482 constraints
.SetTypeKind(TYPE_COMPOUND
);
488 constraints
.SetTypeKind(TYPE_PRIMITIVE
);
489 Type
* baseType
= NULL
;
490 status_t result
= info
->LookupTypeByName(typeName
, constraints
,
494 BReference
<Type
> typeReference(baseType
, true);
495 ArrayType
* arrayType
;
496 result
= baseType
->CreateDerivedArrayType(0, kMaxStringSize
, true,
508 constraints
.SetTypeKind(TYPE_ADDRESS
);
512 return info
->LookupTypeByName(typeName
, constraints
, _type
);
517 BMessageValueNode::_FindField(const char* name
, type_code type
,
518 BMessage::field_header
** result
) const
526 if (fHeader
->field_count
== 0 || fFields
== NULL
|| fData
== NULL
)
527 return B_NAME_NOT_FOUND
;
529 uint32 hash
= _HashName(name
) % fHeader
->hash_table_size
;
530 int32 nextField
= fHeader
->hash_table
[hash
];
532 while (nextField
>= 0) {
533 BMessage::field_header
* field
= &fFields
[nextField
];
534 if ((field
->flags
& FIELD_FLAG_VALID
) == 0)
537 if (strncmp((const char*)(fData
+ field
->offset
), name
,
538 field
->name_length
) == 0) {
539 if (type
!= B_ANY_TYPE
&& field
->type
!= type
)
546 nextField
= field
->next_field
;
549 return B_NAME_NOT_FOUND
;
554 BMessageValueNode::_HashName(const char* name
) const
559 while ((ch
= *name
++) != 0) {
560 result
= (result
<< 7) ^ (result
>> 24);
564 result
^= result
<< 12;
570 BMessageValueNode::_FindDataLocation(const char* name
, type_code type
,
571 int32 index
, ValueLocation
& location
) const
573 BMessage::field_header
* field
= NULL
;
576 status_t result
= _FindField(name
, type
, &field
);
580 if (index
< 0 || (uint32
)index
>= field
->count
)
583 if ((field
->flags
& FIELD_FLAG_FIXED_SIZE
) != 0) {
584 size
= field
->data_size
/ field
->count
;
585 offset
= field
->offset
+ field
->name_length
+ index
* size
;
587 offset
= field
->offset
+ field
->name_length
;
588 uint8
*pointer
= fData
+ field
->offset
+ field
->name_length
;
589 for (int32 i
= 0; i
< index
; i
++) {
590 pointer
+= *(uint32
*)pointer
+ sizeof(uint32
);
591 offset
+= *(uint32
*)pointer
+ sizeof(uint32
);
594 size
= *(uint32
*)pointer
;
595 offset
+= sizeof(uint32
);
598 ValuePieceLocation piece
;
599 piece
.SetToMemory(fDataLocation
.ToUInt64() + offset
);
602 location
.AddPiece(piece
);
608 // #pragma mark - BMessageValueNode::BMessageFieldNode
611 BMessageValueNode::BMessageFieldNode::BMessageFieldNode(
612 BMessageFieldNodeChild
*child
, BMessageValueNode
* parent
,
613 const BString
&name
, type_code type
, int32 count
)
617 fType(parent
->GetType()),
622 fParent
->AcquireReference();
623 fType
->AcquireReference();
627 BMessageValueNode::BMessageFieldNode::~BMessageFieldNode()
629 fParent
->ReleaseReference();
630 fType
->ReleaseReference();
635 BMessageValueNode::BMessageFieldNode::GetType() const
642 BMessageValueNode::BMessageFieldNode::CreateChildren(TeamTypeInformation
* info
)
645 status_t error
= fParent
->_GetTypeForTypeCode(info
, fFieldType
, type
);
649 BReference
<Type
> typeRef(type
, true);
650 for (int32 i
= 0; i
< fFieldCount
; i
++) {
651 BMessageFieldNodeChild
* child
= new(std::nothrow
)
652 BMessageFieldNodeChild(fParent
, type
, fName
, fFieldType
,
658 if (fContainer
!= NULL
)
659 child
->SetContainer(fContainer
);
661 fChildren
.AddItem(child
);
664 fChildrenCreated
= true;
666 if (fContainer
!= NULL
)
667 fContainer
->NotifyValueNodeChildrenCreated(this);
674 BMessageValueNode::BMessageFieldNode::CountChildren() const
676 return fChildren
.CountItems();
680 BMessageValueNode::BMessageFieldNode::ChildAt(int32 index
) const
682 return fChildren
.ItemAt(index
);
687 BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue(
688 ValueLoader
* loader
, ValueLocation
*& _location
, Value
*& _value
)
697 // #pragma mark - BMessageValueNode::BMessageFieldNodeChild
700 BMessageValueNode::BMessageFieldNodeChild::BMessageFieldNodeChild(
701 BMessageValueNode
* parent
, Type
* nodeType
, const BString
&name
,
702 type_code type
, int32 count
, int32 index
)
706 fPresentationName(name
),
713 fParent
->AcquireReference();
714 fType
->AcquireReference();
716 if (fFieldIndex
>= 0)
717 fPresentationName
.SetToFormat("[%" B_PRId32
"]", fFieldIndex
);
721 BMessageValueNode::BMessageFieldNodeChild::~BMessageFieldNodeChild()
723 fParent
->ReleaseReference();
724 fType
->ReleaseReference();
729 BMessageValueNode::BMessageFieldNodeChild::Name() const
731 return fPresentationName
;
736 BMessageValueNode::BMessageFieldNodeChild::GetType() const
743 BMessageValueNode::BMessageFieldNodeChild::Parent() const
750 BMessageValueNode::BMessageFieldNodeChild::IsInternal() const
752 return fFieldCount
> 1 && fFieldIndex
== -1;
757 BMessageValueNode::BMessageFieldNodeChild::CreateInternalNode(
760 BMessageFieldNode
* node
= new(std::nothrow
)
761 BMessageFieldNode(this, fParent
, fName
, fFieldType
, fFieldCount
);
771 BMessageValueNode::BMessageFieldNodeChild::ResolveLocation(
772 ValueLoader
* valueLoader
, ValueLocation
*& _location
)
774 _location
= new(std::nothrow
)ValueLocation();
776 if (_location
== NULL
)
779 return fParent
->_FindDataLocation(fName
, fFieldType
, fFieldIndex
>= 0
780 ? fFieldIndex
: 0, *_location
);