* 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:
Rene Gollent 2011-07-02 20:11:54 +00:00
parent a4dcbd0004
commit ef826895ff
2 changed files with 301 additions and 57 deletions

View File

@ -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);
}

View File

@ -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);