* Restructure things a bit so we store the message's message and field headers
after resolving them. This allows us to reuse BMessage's logic for computing the offsets of values in the data buffer. * Resolve fields to their types and correctly resolve the locations of their data. This means we can now see the values of fields inside the message, with some caveats: string types aren't yet handled properly, and we don't yet properly deal with fields that have multiple indices. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42365 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a4dcbd0004
commit
ef826895ff
@ -15,6 +15,7 @@
|
||||
#include "StringValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "TypeLookupConstraints.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
@ -92,7 +93,10 @@ BMessageValueNode::BMessageValueNode(ValueNodeChild* nodeChild,
|
||||
ValueNode(nodeChild),
|
||||
fType(type),
|
||||
fMessageType(NULL),
|
||||
fMessage()
|
||||
fLoader(NULL),
|
||||
fHeader(NULL),
|
||||
fFields(NULL),
|
||||
fData(NULL)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
@ -103,6 +107,11 @@ BMessageValueNode::~BMessageValueNode()
|
||||
fType->ReleaseReference();
|
||||
for (int32 i = 0; i < fChildren.CountItems(); i++)
|
||||
fChildren.ItemAt(i)->ReleaseReference();
|
||||
|
||||
delete fLoader;
|
||||
delete fHeader;
|
||||
delete[] fFields;
|
||||
delete[] fData;
|
||||
}
|
||||
|
||||
|
||||
@ -162,7 +171,6 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
|
||||
BVariant headerAddress;
|
||||
BVariant fieldAddress;
|
||||
BVariant dataAddress;
|
||||
BVariant what;
|
||||
|
||||
for (int32 i = 0; i < baseType->CountDataMembers(); i++) {
|
||||
@ -224,7 +232,7 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
return error;
|
||||
}
|
||||
error = valueLoader->LoadValue(memberLocation, valueType,
|
||||
false, dataAddress);
|
||||
false, fDataLocation);
|
||||
delete memberLocation;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
@ -235,61 +243,66 @@ BMessageValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
TRACE_LOCALS("BMessage: what: 0x%" B_PRIx32 ", result: %ld\n",
|
||||
what.ToUInt32(), error);
|
||||
|
||||
uint8 headerBuffer[sizeof(BMessage::message_header)];
|
||||
error = valueLoader->LoadRawValue(headerAddress, sizeof(headerBuffer),
|
||||
headerBuffer);
|
||||
|
||||
fHeader = new(std::nothrow) BMessage::message_header();
|
||||
if (fHeader == NULL)
|
||||
return B_NO_MEMORY;
|
||||
error = valueLoader->LoadRawValue(headerAddress, sizeof(
|
||||
BMessage::message_header), fHeader);
|
||||
TRACE_LOCALS("BMessage: Header Address: 0x%" B_PRIx64 ", result: %ld\n",
|
||||
headerAddress.ToUInt64(), error);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
fHeader->what = what.ToUInt32();
|
||||
|
||||
BMessage::message_header* header = (BMessage::message_header*)headerBuffer;
|
||||
header->what = what.ToUInt32();
|
||||
size_t fieldsSize = header->field_count * sizeof(BMessage::field_header);
|
||||
size_t totalMessageSize = sizeof(BMessage::message_header)
|
||||
+ fieldsSize + header->data_size;
|
||||
|
||||
uint8* messageBuffer = new(std::nothrow)uint8[totalMessageSize];
|
||||
size_t fieldsSize = fHeader->field_count * sizeof(
|
||||
BMessage::field_header);
|
||||
size_t totalSize = sizeof(BMessage::message_header) + fieldsSize + fHeader->data_size;
|
||||
uint8* messageBuffer = new(std::nothrow) uint8[totalSize];
|
||||
if (messageBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(messageBuffer, 0, totalMessageSize);
|
||||
|
||||
ArrayDeleter<uint8> deleter(messageBuffer);
|
||||
|
||||
// This more or less follows the logic of BMessage::Flatten
|
||||
// in order to reconstruct the flattened buffer ; thus if the
|
||||
// internal representation of that changes, this will have to
|
||||
// follow suit
|
||||
uint8* currentBuffer = messageBuffer;
|
||||
memcpy(currentBuffer, header,
|
||||
sizeof(BMessage::message_header));
|
||||
|
||||
memset(messageBuffer, 0, totalSize);
|
||||
memcpy(messageBuffer, fHeader, sizeof(BMessage::message_header));
|
||||
uint8* tempBuffer = messageBuffer + sizeof(BMessage::message_header);
|
||||
if (fieldsSize > 0) {
|
||||
currentBuffer += sizeof(BMessage::message_header);
|
||||
fFields = new(std::nothrow)
|
||||
BMessage::field_header[fHeader->field_count];
|
||||
if (fFields == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
error = valueLoader->LoadRawValue(fieldAddress, fieldsSize,
|
||||
currentBuffer);
|
||||
fFields);
|
||||
TRACE_LOCALS("BMessage: Field Header Address: 0x%" B_PRIx64
|
||||
", result: %ld\n", headerAddress.ToUInt64(), error);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
headerAddress.SetTo(dataAddress);
|
||||
currentBuffer += fieldsSize;
|
||||
error = valueLoader->LoadRawValue(dataAddress, header->data_size,
|
||||
currentBuffer);
|
||||
TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64 ", result: %ld\n",
|
||||
headerAddress.ToUInt64(), error);
|
||||
fData = new(std::nothrow) uint8[fHeader->data_size];
|
||||
if (fData == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
error = valueLoader->LoadRawValue(fDataLocation, fHeader->data_size,
|
||||
fData);
|
||||
TRACE_LOCALS("BMessage: Data Address: 0x%" B_PRIx64
|
||||
", result: %ld\n", fDataLocation.ToUInt64(), error);
|
||||
if (error != B_OK)
|
||||
return B_ERROR;
|
||||
return error;
|
||||
memcpy(tempBuffer, fFields, fieldsSize);
|
||||
tempBuffer += fieldsSize;
|
||||
memcpy(tempBuffer, fData, fHeader->data_size);
|
||||
}
|
||||
|
||||
error = fMessage.Unflatten((const char *)messageBuffer);
|
||||
TRACE_LOCALS("BMessage: Unflatten result: %s\n", strerror(error));
|
||||
|
||||
error = fMessage.Unflatten((const char*)messageBuffer);
|
||||
delete[] messageBuffer;
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (fLoader == NULL) {
|
||||
fLoader = new(std::nothrow)ValueLoader(*valueLoader);
|
||||
if (fLoader == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -303,7 +316,6 @@ BMessageValueNode::CreateChildren()
|
||||
if (fMessageType == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
|
||||
DataMember* member = NULL;
|
||||
Type* whatType = NULL;
|
||||
|
||||
@ -326,13 +338,16 @@ BMessageValueNode::CreateChildren()
|
||||
char* name;
|
||||
type_code type;
|
||||
int32 count;
|
||||
for (int32 i = 0;
|
||||
fMessage.GetInfo(B_ANY_TYPE, i, &name, &type, &count) == B_OK;
|
||||
i++) {
|
||||
// TODO: split FieldHeaderNode into two variants in order to
|
||||
// present fields with a count of 1 without subindices.
|
||||
Type* fieldType = NULL;
|
||||
for (int32 i = 0; fMessage.GetInfo(B_ANY_TYPE, i, &name, &type,
|
||||
&count) == B_OK; i++) {
|
||||
fieldType = NULL;
|
||||
|
||||
_GetTypeForTypeCode(type, fieldType);
|
||||
|
||||
BMessageFieldNodeChild* node = new(std::nothrow)
|
||||
BMessageFieldNodeChild(this, name, type, count);
|
||||
BMessageFieldNodeChild(this, fieldType != NULL ? fieldType : fType,
|
||||
name, type, count);
|
||||
if (node == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@ -361,15 +376,220 @@ BMessageValueNode::ChildAt(int32 index) const
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageValueNode::_GetTypeForTypeCode(type_code type,
|
||||
Type*& _type)
|
||||
{
|
||||
BString typeName;
|
||||
TypeLookupConstraints constraints;
|
||||
|
||||
switch(type) {
|
||||
case B_BOOL_TYPE:
|
||||
typeName = "bool";
|
||||
constraints.SetTypeKind(TYPE_PRIMITIVE);
|
||||
break;
|
||||
|
||||
case B_INT8_TYPE:
|
||||
typeName = "int8";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_UINT8_TYPE:
|
||||
typeName = "uint8";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_INT16_TYPE:
|
||||
typeName = "int16";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_UINT16_TYPE:
|
||||
typeName = "uint16";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_INT32_TYPE:
|
||||
typeName = "int32";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_UINT32_TYPE:
|
||||
typeName = "uint32";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_INT64_TYPE:
|
||||
typeName = "int64";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_UINT64_TYPE:
|
||||
typeName = "uint64";
|
||||
constraints.SetTypeKind(TYPE_TYPEDEF);
|
||||
break;
|
||||
|
||||
case B_FLOAT_TYPE:
|
||||
typeName = "float";
|
||||
constraints.SetTypeKind(TYPE_PRIMITIVE);
|
||||
break;
|
||||
|
||||
case B_DOUBLE_TYPE:
|
||||
typeName = "double";
|
||||
constraints.SetTypeKind(TYPE_PRIMITIVE);
|
||||
break;
|
||||
|
||||
case B_MESSAGE_TYPE:
|
||||
typeName = "BMessage";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_MESSENGER_TYPE:
|
||||
typeName = "BMessenger";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_POINT_TYPE:
|
||||
typeName = "BPoint";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_POINTER_TYPE:
|
||||
typeName = "void";
|
||||
constraints.SetTypeKind(TYPE_ADDRESS);
|
||||
break;
|
||||
|
||||
case B_RECT_TYPE:
|
||||
typeName = "BRect";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_REF_TYPE:
|
||||
typeName = "entry_ref";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_RGB_COLOR_TYPE:
|
||||
typeName = "rgb_color";
|
||||
constraints.SetTypeKind(TYPE_COMPOUND);
|
||||
break;
|
||||
|
||||
case B_STRING_TYPE:
|
||||
typeName = "char";
|
||||
constraints.SetTypeKind(TYPE_ARRAY);
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return fLoader->LookupTypeByName(typeName, constraints, _type);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageValueNode::_FindField(const char* name, type_code type,
|
||||
BMessage::field_header** result) const
|
||||
{
|
||||
if (name == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (fHeader == NULL)
|
||||
return B_NO_INIT;
|
||||
|
||||
if (fHeader->field_count == 0 || fFields == NULL || fData == NULL)
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
uint32 hash = _HashName(name) % fHeader->hash_table_size;
|
||||
int32 nextField = fHeader->hash_table[hash];
|
||||
|
||||
while (nextField >= 0) {
|
||||
BMessage::field_header* field = &fFields[nextField];
|
||||
if ((field->flags & FIELD_FLAG_VALID) == 0)
|
||||
break;
|
||||
|
||||
if (strncmp((const char*)(fData + field->offset), name,
|
||||
field->name_length) == 0) {
|
||||
if (type != B_ANY_TYPE && field->type != type)
|
||||
return B_BAD_TYPE;
|
||||
|
||||
*result = field;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
nextField = field->next_field;
|
||||
}
|
||||
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BMessageValueNode::_HashName(const char* name) const
|
||||
{
|
||||
char ch;
|
||||
uint32 result = 0;
|
||||
|
||||
while ((ch = *name++) != 0) {
|
||||
result = (result << 7) ^ (result >> 24);
|
||||
result ^= ch;
|
||||
}
|
||||
|
||||
result ^= result << 12;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageValueNode::_FindDataLocation(const char* name, type_code type,
|
||||
int32 index, ValueLocation& location) const
|
||||
{
|
||||
BMessage::field_header* field = NULL;
|
||||
int32 offset = 0;
|
||||
int32 size = 0;
|
||||
status_t result = _FindField(name, type, &field);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (index < 0 || (uint32)index >= field->count)
|
||||
return B_BAD_INDEX;
|
||||
|
||||
if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) {
|
||||
size = field->data_size / field->count;
|
||||
offset = field->offset + field->name_length + index * size;
|
||||
} else {
|
||||
offset = field->offset + field->name_length;
|
||||
uint8 *pointer = fData + field->offset + field->name_length;
|
||||
for (int32 i = 0; i < index; i++) {
|
||||
pointer += *(uint32*)pointer + sizeof(uint32);
|
||||
offset += *(uint32*)pointer + sizeof(uint32);
|
||||
}
|
||||
|
||||
size = *(uint32*)pointer;
|
||||
offset += sizeof(uint32);
|
||||
}
|
||||
|
||||
ValuePieceLocation piece;
|
||||
piece.SetToMemory(fDataLocation.ToUInt64() + offset);
|
||||
piece.SetSize(size);
|
||||
location.Clear();
|
||||
location.AddPiece(piece);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BMessageValueNode::BMessageFieldNode
|
||||
|
||||
|
||||
BMessageValueNode::BMessageFieldNode::BMessageFieldNode(
|
||||
BMessageFieldNodeChild *child, BMessageValueNode* parent,
|
||||
const BString &name, type_code type, int32 count)
|
||||
:
|
||||
ValueNode(child),
|
||||
fName(name),
|
||||
fType(parent->GetType()),
|
||||
fType(parent->fMessageType),
|
||||
fParent(parent),
|
||||
fFieldType(type),
|
||||
fFieldCount(count)
|
||||
@ -428,12 +648,12 @@ BMessageValueNode::BMessageFieldNode::ResolvedLocationAndValue(
|
||||
|
||||
|
||||
BMessageValueNode::BMessageFieldNodeChild::BMessageFieldNodeChild(
|
||||
BMessageValueNode* parent, const BString &name, type_code type,
|
||||
int32 count)
|
||||
BMessageValueNode* parent, Type* nodeType, const BString &name,
|
||||
type_code type, int32 count)
|
||||
:
|
||||
ValueNodeChild(),
|
||||
fName(name),
|
||||
fType(parent->GetType()),
|
||||
fType(nodeType),
|
||||
fParent(parent),
|
||||
fFieldType(type),
|
||||
fFieldCount(count)
|
||||
@ -474,7 +694,7 @@ BMessageValueNode::BMessageFieldNodeChild::Parent() const
|
||||
bool
|
||||
BMessageValueNode::BMessageFieldNodeChild::IsInternal() const
|
||||
{
|
||||
return true;
|
||||
return fFieldCount > 1;
|
||||
}
|
||||
|
||||
|
||||
@ -496,7 +716,10 @@ status_t
|
||||
BMessageValueNode::BMessageFieldNodeChild::ResolveLocation(
|
||||
ValueLoader* valueLoader, ValueLocation*& _location)
|
||||
{
|
||||
_location = fParent->Location();
|
||||
_location = new(std::nothrow)ValueLocation();
|
||||
|
||||
return B_OK;
|
||||
if (_location == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return fParent->_FindDataLocation(fName, fFieldType, 0, *_location);
|
||||
}
|
||||
|
@ -6,8 +6,11 @@
|
||||
#define BMESSAGE_VALUE_NODE_H
|
||||
|
||||
#include <Message.h>
|
||||
#include <MessagePrivate.h>
|
||||
#include <ObjectList.h>
|
||||
#include <Variant.h>
|
||||
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
@ -35,6 +38,17 @@ public:
|
||||
CompoundType* GetMessageType() const
|
||||
{ return fMessageType; }
|
||||
|
||||
private:
|
||||
status_t _GetTypeForTypeCode(type_code type,
|
||||
Type*& _type);
|
||||
status_t _FindField(const char* name,
|
||||
type_code type,
|
||||
BMessage::field_header** result) const;
|
||||
uint32 _HashName(const char* name) const;
|
||||
status_t _FindDataLocation(const char* name,
|
||||
type_code type, int32 index,
|
||||
ValueLocation& location) const;
|
||||
|
||||
private:
|
||||
class BMessageFieldNode;
|
||||
class BMessageFieldNodeChild;
|
||||
@ -48,8 +62,14 @@ private:
|
||||
private:
|
||||
Type* fType;
|
||||
CompoundType* fMessageType;
|
||||
BMessage fMessage;
|
||||
ChildNodeList fChildren;
|
||||
ValueLoader* fLoader;
|
||||
BVariant fDataLocation;
|
||||
BMessage::message_header*
|
||||
fHeader;
|
||||
BMessage::field_header* fFields;
|
||||
uint8* fData;
|
||||
BMessage fMessage;
|
||||
};
|
||||
|
||||
|
||||
@ -65,15 +85,15 @@ public:
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* loader,
|
||||
ValueLocation *& _location,
|
||||
Value*& _value);
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
Type* fType;
|
||||
@ -87,6 +107,7 @@ class BMessageValueNode::BMessageFieldNodeChild : public ValueNodeChild {
|
||||
public:
|
||||
BMessageFieldNodeChild(
|
||||
BMessageValueNode* parent,
|
||||
Type* nodeType,
|
||||
const BString &name,
|
||||
type_code type, int32 count);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user