headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / debugger / value / value_nodes / BMessageValueNode.cpp
blobe65cc91087bad13f6b761bebc9d1b5c5f6ce9b33
1 /*
2 * Copyright 2011-2015, Rene Gollent, rene@gollent.com
3 * Distributed under the terms of the MIT License.
4 */
7 #include "BMessageValueNode.h"
9 #include <new>
11 #include <AutoDeleter.h>
12 #include <MessageAdapter.h>
13 #include <MessagePrivate.h>
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"
26 static const int64 kMaxStringSize = 64;
29 // #pragma mark - BMessageWhatNodeChild
32 class BMessageWhatNodeChild : public ValueNodeChild {
33 public:
34 BMessageWhatNodeChild(BMessageValueNode* parent, DataMember* member,
35 Type* type)
37 ValueNodeChild(),
38 fMember(member),
39 fName("what"),
40 fParent(parent),
41 fType(type)
43 fParent->AcquireReference();
44 fType->AcquireReference();
47 virtual ~BMessageWhatNodeChild()
49 fParent->ReleaseReference();
50 fType->ReleaseReference();
53 virtual const BString& Name() const
55 return fName;
58 virtual Type* GetType() const
60 return fType;
63 virtual ValueNode* Parent() const
65 return fParent;
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();
77 if (location == NULL)
78 return B_NO_MEMORY;
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);
90 if (error != B_OK)
91 return error;
93 _location = location;
94 return B_OK;
97 private:
98 DataMember* fMember;
99 BString fName;
100 BMessageValueNode* fParent;
101 Type* fType;
105 // #pragma mark - BMessageValueNode
108 BMessageValueNode::BMessageValueNode(ValueNodeChild* nodeChild,
109 Type* type)
111 ValueNode(nodeChild),
112 fType(type),
113 fHeader(NULL),
114 fFields(NULL),
115 fData(NULL),
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();
128 delete fHeader;
129 delete[] fFields;
130 delete[] fData;
134 Type*
135 BMessageValueNode::GetType() const
137 return fType;
141 status_t
142 BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
143 ValueLocation*& _location, Value*& _value)
145 fIsFlatMessage = dynamic_cast<BMessageFieldNodeChild*>(NodeChild())
146 != NULL;
148 // get the location
149 ValueLocation* location = NodeChild()->Location();
150 if (location == NULL)
151 return B_BAD_VALUE;
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");
164 // load the value data
166 status_t error = B_OK;
167 _location = location;
168 _value = NULL;
170 ValueLocation* memberLocation = NULL;
172 BVariant headerAddress;
173 BVariant fieldAddress;
174 BVariant what;
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));
182 } else {
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);
189 if (error != B_OK) {
190 TRACE_LOCALS(
191 "BMessageValueNode::ResolvedLocationAndValue(): "
192 "failed to resolve location of header member: %s\n",
193 strerror(error));
194 return error;
197 error = valueLoader->LoadValue(memberLocation, valueType,
198 false, headerAddress);
199 if (error != B_OK)
200 return error;
201 } else if (strcmp(member->Name(), "what") == 0) {
202 error = baseType->ResolveDataMemberLocation(member,
203 *location, memberLocation);
204 BReference<ValueLocation> locationRef(memberLocation, true);
205 if (error != B_OK) {
206 TRACE_LOCALS(
207 "BMessageValueNode::ResolvedLocationAndValue(): "
208 "failed to resolve location of header member: %s\n",
209 strerror(error));
210 return error;
212 error = valueLoader->LoadValue(memberLocation, B_UINT32_TYPE,
213 false, what);
214 if (error != B_OK)
215 return error;
216 } else if (strcmp(member->Name(), "fFields") == 0) {
217 error = baseType->ResolveDataMemberLocation(member,
218 *location, memberLocation);
219 BReference<ValueLocation> locationRef(memberLocation, true);
220 if (error != B_OK) {
221 TRACE_LOCALS(
222 "BMessageValueNode::ResolvedLocationAndValue(): "
223 "failed to resolve location of field member: %s\n",
224 strerror(error));
225 return error;
227 error = valueLoader->LoadValue(memberLocation, valueType,
228 false, fieldAddress);
229 if (error != B_OK)
230 return error;
231 } else if (strcmp(member->Name(), "fData") == 0) {
232 error = baseType->ResolveDataMemberLocation(member,
233 *location, memberLocation);
234 BReference<ValueLocation> locationRef(memberLocation, true);
235 if (error != B_OK) {
236 TRACE_LOCALS(
237 "BMessageValueNode::ResolvedLocationAndValue(): "
238 "failed to resolve location of data member: %s\n",
239 strerror(error));
240 return error;
242 error = valueLoader->LoadValue(memberLocation, valueType,
243 false, fDataLocation);
244 if (error != B_OK)
245 return error;
247 memberLocation = NULL;
251 fHeader = new(std::nothrow) BMessage::message_header();
252 if (fHeader == NULL)
253 return B_NO_MEMORY;
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));
258 if (error != B_OK)
259 return error;
261 if (fHeader->format != MESSAGE_FORMAT_HAIKU
262 || (fHeader->flags & MESSAGE_FLAG_VALID) == 0)
263 return B_NOT_A_MESSAGE;
265 if (fIsFlatMessage)
266 what.SetTo(fHeader->what);
267 else
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);
275 if (fIsFlatMessage)
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)
282 return B_NO_MEMORY;
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];
292 if (fFields == NULL)
293 return B_NO_MEMORY;
295 error = valueLoader->LoadRawValue(fieldAddress, fieldsSize,
296 fFields);
297 TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64
298 ", result: %s\n", headerAddress.ToUInt64(), strerror(error));
299 if (error != B_OK)
300 return error;
302 fData = new(std::nothrow) uint8[fHeader->data_size];
303 if (fData == NULL)
304 return B_NO_MEMORY;
306 error = valueLoader->LoadRawValue(fDataLocation, fHeader->data_size,
307 fData);
308 TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64
309 ", result: %s\n", fDataLocation.ToUInt64(), strerror(error));
310 if (error != B_OK)
311 return error;
312 memcpy(tempBuffer, fFields, fieldsSize);
313 tempBuffer += fieldsSize;
314 memcpy(tempBuffer, fData, fHeader->data_size);
317 error = fMessage.Unflatten((const char*)messageBuffer);
318 if (error != B_OK)
319 return error;
321 return B_OK;
325 status_t
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,
335 member->GetType());
336 if (whatNode == NULL)
337 return B_NO_MEMORY;
339 whatNode->SetContainer(fContainer);
340 fChildren.AddItem(whatNode);
341 break;
345 char* name;
346 type_code type;
347 int32 count;
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++) {
352 fieldType = NULL;
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,
361 count);
362 if (node == NULL)
363 return B_NO_MEMORY;
365 node->SetContainer(fContainer);
366 fChildren.AddItem(node);
369 fChildrenCreated = true;
371 if (fContainer != NULL)
372 fContainer->NotifyValueNodeChildrenCreated(this);
374 return B_OK;
378 int32
379 BMessageValueNode::CountChildren() const
381 return fChildren.CountItems();
385 ValueNodeChild*
386 BMessageValueNode::ChildAt(int32 index) const
388 return fChildren.ItemAt(index);
392 status_t
393 BMessageValueNode::_GetTypeForTypeCode(TeamTypeInformation* info,
394 type_code type, Type*& _type)
396 BString typeName;
397 TypeLookupConstraints constraints;
399 switch(type) {
400 case B_BOOL_TYPE:
401 typeName = "bool";
402 constraints.SetTypeKind(TYPE_PRIMITIVE);
403 break;
405 case B_INT8_TYPE:
406 typeName = "int8";
407 constraints.SetTypeKind(TYPE_TYPEDEF);
408 break;
410 case B_UINT8_TYPE:
411 typeName = "uint8";
412 constraints.SetTypeKind(TYPE_TYPEDEF);
413 break;
415 case B_INT16_TYPE:
416 typeName = "int16";
417 constraints.SetTypeKind(TYPE_TYPEDEF);
418 break;
420 case B_UINT16_TYPE:
421 typeName = "uint16";
422 constraints.SetTypeKind(TYPE_TYPEDEF);
423 break;
425 case B_INT32_TYPE:
426 typeName = "int32";
427 constraints.SetTypeKind(TYPE_TYPEDEF);
428 break;
430 case B_UINT32_TYPE:
431 typeName = "uint32";
432 constraints.SetTypeKind(TYPE_TYPEDEF);
433 break;
435 case B_INT64_TYPE:
436 typeName = "int64";
437 constraints.SetTypeKind(TYPE_TYPEDEF);
438 break;
440 case B_UINT64_TYPE:
441 typeName = "uint64";
442 constraints.SetTypeKind(TYPE_TYPEDEF);
443 break;
445 case B_FLOAT_TYPE:
446 typeName = "float";
447 constraints.SetTypeKind(TYPE_PRIMITIVE);
448 break;
450 case B_DOUBLE_TYPE:
451 typeName = "double";
452 constraints.SetTypeKind(TYPE_PRIMITIVE);
453 break;
455 case B_MESSAGE_TYPE:
456 typeName = "BMessage";
457 constraints.SetTypeKind(TYPE_COMPOUND);
458 break;
460 case B_MESSENGER_TYPE:
461 typeName = "BMessenger";
462 constraints.SetTypeKind(TYPE_COMPOUND);
463 break;
465 case B_POINT_TYPE:
466 typeName = "BPoint";
467 constraints.SetTypeKind(TYPE_COMPOUND);
468 break;
470 case B_RECT_TYPE:
471 typeName = "BRect";
472 constraints.SetTypeKind(TYPE_COMPOUND);
473 break;
475 case B_REF_TYPE:
476 typeName = "entry_ref";
477 constraints.SetTypeKind(TYPE_COMPOUND);
478 break;
480 case B_RGB_COLOR_TYPE:
481 typeName = "rgb_color";
482 constraints.SetTypeKind(TYPE_COMPOUND);
483 break;
485 case B_STRING_TYPE:
487 typeName = "char";
488 constraints.SetTypeKind(TYPE_PRIMITIVE);
489 Type* baseType = NULL;
490 status_t result = info->LookupTypeByName(typeName, constraints,
491 baseType);
492 if (result != B_OK)
493 return result;
494 BReference<Type> typeReference(baseType, true);
495 ArrayType* arrayType;
496 result = baseType->CreateDerivedArrayType(0, kMaxStringSize, true,
497 arrayType);
498 if (result == B_OK)
499 _type = arrayType;
501 return result;
502 break;
505 case B_POINTER_TYPE:
506 default:
507 typeName = "void*";
508 constraints.SetTypeKind(TYPE_ADDRESS);
509 break;
512 return info->LookupTypeByName(typeName, constraints, _type);
516 status_t
517 BMessageValueNode::_FindField(const char* name, type_code type,
518 BMessage::field_header** result) const
520 if (name == NULL)
521 return B_BAD_VALUE;
523 if (fHeader == NULL)
524 return B_NO_INIT;
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)
535 break;
537 if (strncmp((const char*)(fData + field->offset), name,
538 field->name_length) == 0) {
539 if (type != B_ANY_TYPE && field->type != type)
540 return B_BAD_TYPE;
542 *result = field;
543 return B_OK;
546 nextField = field->next_field;
549 return B_NAME_NOT_FOUND;
553 uint32
554 BMessageValueNode::_HashName(const char* name) const
556 char ch;
557 uint32 result = 0;
559 while ((ch = *name++) != 0) {
560 result = (result << 7) ^ (result >> 24);
561 result ^= ch;
564 result ^= result << 12;
565 return result;
569 status_t
570 BMessageValueNode::_FindDataLocation(const char* name, type_code type,
571 int32 index, ValueLocation& location) const
573 BMessage::field_header* field = NULL;
574 int32 offset = 0;
575 int32 size = 0;
576 status_t result = _FindField(name, type, &field);
577 if (result != B_OK)
578 return result;
580 if (index < 0 || (uint32)index >= field->count)
581 return B_BAD_INDEX;
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;
586 } else {
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);
600 piece.SetSize(size);
601 location.Clear();
602 location.AddPiece(piece);
604 return B_OK;
608 // #pragma mark - BMessageValueNode::BMessageFieldNode
611 BMessageValueNode::BMessageFieldNode::BMessageFieldNode(
612 BMessageFieldNodeChild *child, BMessageValueNode* parent,
613 const BString &name, type_code type, int32 count)
615 ValueNode(child),
616 fName(name),
617 fType(parent->GetType()),
618 fParent(parent),
619 fFieldType(type),
620 fFieldCount(count)
622 fParent->AcquireReference();
623 fType->AcquireReference();
627 BMessageValueNode::BMessageFieldNode::~BMessageFieldNode()
629 fParent->ReleaseReference();
630 fType->ReleaseReference();
634 Type*
635 BMessageValueNode::BMessageFieldNode::GetType() const
637 return fType;
641 status_t
642 BMessageValueNode::BMessageFieldNode::CreateChildren(TeamTypeInformation* info)
644 Type* type = NULL;
645 status_t error = fParent->_GetTypeForTypeCode(info, fFieldType, type);
646 if (error != B_OK)
647 return error;
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,
653 fFieldCount, i);
655 if (child == NULL)
656 return B_NO_MEMORY;
658 if (fContainer != NULL)
659 child->SetContainer(fContainer);
661 fChildren.AddItem(child);
664 fChildrenCreated = true;
666 if (fContainer != NULL)
667 fContainer->NotifyValueNodeChildrenCreated(this);
669 return B_OK;
673 int32
674 BMessageValueNode::BMessageFieldNode::CountChildren() const
676 return fChildren.CountItems();
679 ValueNodeChild*
680 BMessageValueNode::BMessageFieldNode::ChildAt(int32 index) const
682 return fChildren.ItemAt(index);
686 status_t
687 BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue(
688 ValueLoader* loader, ValueLocation *& _location, Value*& _value)
690 _location = NULL;
691 _value = NULL;
693 return B_OK;
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)
704 ValueNodeChild(),
705 fName(name),
706 fPresentationName(name),
707 fType(nodeType),
708 fParent(parent),
709 fFieldType(type),
710 fFieldCount(count),
711 fFieldIndex(index)
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();
728 const BString&
729 BMessageValueNode::BMessageFieldNodeChild::Name() const
731 return fPresentationName;
735 Type*
736 BMessageValueNode::BMessageFieldNodeChild::GetType() const
738 return fType;
742 ValueNode*
743 BMessageValueNode::BMessageFieldNodeChild::Parent() const
745 return fParent;
749 bool
750 BMessageValueNode::BMessageFieldNodeChild::IsInternal() const
752 return fFieldCount > 1 && fFieldIndex == -1;
756 status_t
757 BMessageValueNode::BMessageFieldNodeChild::CreateInternalNode(
758 ValueNode*& _node)
760 BMessageFieldNode* node = new(std::nothrow)
761 BMessageFieldNode(this, fParent, fName, fFieldType, fFieldCount);
762 if (node == NULL)
763 return B_NO_MEMORY;
765 _node = node;
766 return B_OK;
770 status_t
771 BMessageValueNode::BMessageFieldNodeChild::ResolveLocation(
772 ValueLoader* valueLoader, ValueLocation*& _location)
774 _location = new(std::nothrow)ValueLocation();
776 if (_location == NULL)
777 return B_NO_MEMORY;
779 return fParent->_FindDataLocation(fName, fFieldType, fFieldIndex >= 0
780 ? fFieldIndex : 0, *_location);