Actually the Message3 implementation was broken. It still is, because we lose one (but an important) byte somewhere when resizing the flat buffer. But at least the design flaws should be corrected with this commit. You can go ahead and review it Ingo.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13917 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2005-08-09 05:49:13 +00:00
parent 3019039f4f
commit 90dc946130
5 changed files with 92 additions and 79 deletions

View File

@ -12,7 +12,6 @@
#define _MESSAGE_BODY_H_ #define _MESSAGE_BODY_H_
#include <List.h> #include <List.h>
#include "MessageField3.h"
enum { enum {
B_FLATTENABLE_TYPE = 'FLAT' B_FLATTENABLE_TYPE = 'FLAT'
@ -20,6 +19,8 @@ enum {
namespace BPrivate { namespace BPrivate {
class BMessageField;
class BMessageBody { class BMessageBody {
public: public:
BMessageBody(); BMessageBody();
@ -68,7 +69,7 @@ public:
void PrintToStream() const; void PrintToStream() const;
// flat buffer management // flat buffer management
uint8 *FlatBuffer() const { return (uint8 *)fFlatBuffer.Buffer(); }; inline uint8 *FlatBuffer() const { return (uint8 *)fFlatBuffer.Buffer(); };
uint8 *FlatInsert(int32 offset, ssize_t oldLength, uint8 *FlatInsert(int32 offset, ssize_t oldLength,
ssize_t newLength); ssize_t newLength);

View File

@ -14,6 +14,7 @@
#include <List.h> #include <List.h>
#include <String.h> #include <String.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "MessageBody3.h"
// we only support those // we only support those
#define MSG_FLAG_VALID 0x01 #define MSG_FLAG_VALID 0x01
@ -56,27 +57,24 @@ struct item_info_s {
typedef field_header_s FieldHeader; typedef field_header_s FieldHeader;
typedef item_info_s ItemInfo; typedef item_info_s ItemInfo;
class BMessageBody;
class BMessageField { class BMessageField {
public: public:
BMessageField(BMessageBody *parent, BMessageField(BMessageBody *parent,
int32 offset, const char *name, int32 offset, const char *name,
type_code type); type_code type);
// only use this constructor to unflatten
BMessageField(BMessageBody *parent); BMessageField(BMessageBody *parent);
~BMessageField();
int32 Unflatten(int32 offset); int32 Unflatten(int32 offset);
uint8 Flags() const { return fHeader->flags; }; uint8 Flags() const { return Header()->flags; };
status_t SetFixedSize(int32 itemSize); status_t SetFixedSize(int32 itemSize);
bool FixedSize() const { return fHeader->flags & MSG_FLAG_FIXED_SIZE; }; bool FixedSize() const { return fFixedSize; };
void SetName(const char *newName); void SetName(const char *newName);
const char *Name() const; const char *Name() const;
uint8 NameLength() const { return fHeader->nameLength; }; uint8 NameLength() const { return Header()->nameLength; };
type_code Type() const { return fHeader->type; }; type_code Type() const { return Header()->type; };
void AddItem(const void *item, ssize_t length); void AddItem(const void *item, ssize_t length);
uint8 *AddItem(ssize_t length); uint8 *AddItem(ssize_t length);
@ -88,11 +86,11 @@ public:
void *ItemAt(int32 index, ssize_t *size); void *ItemAt(int32 index, ssize_t *size);
void RemoveItem(int32 index); void RemoveItem(int32 index);
int32 CountItems() const { return fHeader->count; }; int32 CountItems() const { return Header()->count; };
void PrintToStream() const; void PrintToStream() const;
void SetOffset(int32 offset); void SetOffset(int32 offset) { fOffset = offset; };
int32 Offset() const { return fOffset; }; int32 Offset() const { return fOffset; };
// always do MakeEmpty -> RemoveSelf -> delete // always do MakeEmpty -> RemoveSelf -> delete
@ -104,12 +102,13 @@ public:
BMessageField *Next() const { return fNext; }; BMessageField *Next() const { return fNext; };
private: private:
bool IsFixedSize(type_code type); inline FieldHeader *Header() const { return (FieldHeader *)(fParent->FlatBuffer() + fOffset); };
BMessageBody *fParent; BMessageBody *fParent;
int32 fOffset; int32 fOffset;
FieldHeader *fHeader; int32 fDataOffset;
bool fFixedSize;
int32 fItemSize; int32 fItemSize;
BList fItemInfos; BList fItemInfos;

View File

@ -593,9 +593,10 @@ BMessage::IsReply() const
void void
BMessage::PrintToStream() const BMessage::PrintToStream() const
{ {
printf("\nBMessage: what = '%c%c%c%c' (0x%lX or %ld)\n", printf("\nBMessage: what = ");
(uint8)(what >> 24), (uint8)(what >> 16), (uint8)(what >> 8), printf("%c%c%c%c", (uint8)(what >> 24), (uint8)(what >> 16),
(uint8)what, what, what); (uint8)(what >> 8), (uint8)what);
printf(" (0x%lX or %ld)\n", what, what);
fBody->PrintToStream(); fBody->PrintToStream();
} }
@ -1053,7 +1054,8 @@ BMessage::Find ## fnName(const char *name, int32 index, TYPE *p) const \
status_t error = B_OK; \ status_t error = B_OK; \
\ \
*p = TYPE(); \ *p = TYPE(); \
error = fBody->FindData(name, TYPESPEC, index, (const void **)&ptr, &bytes); \ error = fBody->FindData(name, TYPESPEC, index, (const void **)&ptr, \
&bytes); \
\ \
if (error == B_OK) \ if (error == B_OK) \
memcpy(p, ptr, sizeof(TYPE)); \ memcpy(p, ptr, sizeof(TYPE)); \

View File

@ -12,6 +12,7 @@
#include <DataIO.h> #include <DataIO.h>
#include <TypeConstants.h> #include <TypeConstants.h>
#include "MessageBody3.h" #include "MessageBody3.h"
#include "MessageField3.h"
#include "MessageUtils3.h" #include "MessageUtils3.h"
namespace BPrivate { namespace BPrivate {
@ -237,10 +238,9 @@ BMessageBody::Unflatten(BDataIO *stream, int32 length)
int32 offset = 0; int32 offset = 0;
uint8 *location = (uint8 *)fFlatBuffer.Buffer(); uint8 *location = (uint8 *)fFlatBuffer.Buffer();
while (offset < length && *location & MSG_FLAG_VALID) { while (offset < error && *location & MSG_FLAG_VALID) {
BMessageField *field = new BMessageField(this); BMessageField *field = new BMessageField(this);
int32 fieldLength = field->Unflatten(offset); int32 fieldLength = field->Unflatten(offset);
//PrintToStream();
if (fieldLength <= 0) { if (fieldLength <= 0) {
field->MakeEmpty(); field->MakeEmpty();

View File

@ -14,7 +14,7 @@
namespace BPrivate { namespace BPrivate {
#define DATA_OFFSET (fOffset + sizeof(FieldHeader) + fHeader->nameLength) #define DATA_OFFSET (fOffset + fDataOffset)
inline int32 inline int32
round_to_8(int32 length) round_to_8(int32 length)
@ -28,18 +28,22 @@ BMessageField::BMessageField(BMessageBody *parent, int32 offset,
const char *name, type_code type) const char *name, type_code type)
: fParent(parent), : fParent(parent),
fOffset(offset), fOffset(offset),
fItemSize(0) fDataOffset(0),
fFixedSize(false),
fItemSize(0),
fItemInfos(5),
fNext(NULL)
{ {
// insert space needed for the header // insert space needed for the header
fParent->FlatInsert(fOffset, 0, sizeof(FieldHeader)); fParent->FlatInsert(fOffset, 0, sizeof(FieldHeader));
// create and fill header // fill the header
fHeader = (FieldHeader *)(fParent->FlatBuffer() + fOffset); FieldHeader *header = Header();
fHeader->type = type; header->type = type;
fHeader->flags = MSG_FLAG_VALID; header->flags = MSG_FLAG_VALID;
fHeader->count = 0; header->count = 0;
fHeader->dataSize = 0; header->dataSize = 0;
fHeader->nameLength = 0; header->nameLength = 0;
SetName(name); SetName(name);
} }
@ -48,13 +52,11 @@ BMessageField::BMessageField(BMessageBody *parent, int32 offset,
BMessageField::BMessageField(BMessageBody *parent) BMessageField::BMessageField(BMessageBody *parent)
: fParent(parent), : fParent(parent),
fOffset(0), fOffset(0),
fHeader(NULL), fDataOffset(0),
fItemSize(0) fFixedSize(false),
{ fItemSize(0),
} fItemInfos(5),
fNext(NULL)
BMessageField::~BMessageField()
{ {
} }
@ -65,18 +67,23 @@ BMessageField::Unflatten(int32 _offset)
fOffset = _offset; fOffset = _offset;
// field is already present, just tap into it // field is already present, just tap into it
fHeader = (FieldHeader *)(fParent->FlatBuffer() + fOffset); FieldHeader *header = Header();
fDataOffset = sizeof(FieldHeader) + header->nameLength;
fFixedSize = header->flags & MSG_FLAG_FIXED_SIZE;
if (fHeader->flags & MSG_FLAG_FIXED_SIZE) { if (header->nameLength == 0)
if (fHeader->count > 0) return 0;
fItemSize = fHeader->dataSize / fHeader->count;
return sizeof(FieldHeader) + fHeader->nameLength + fHeader->count * fItemSize; if (fFixedSize) {
if (header->count > 0)
fItemSize = header->dataSize / header->count;
return fDataOffset + header->count * fItemSize;
} }
// create the item info list // create the item info list
int32 offset = 0; int32 offset = 0;
uint8 *location = fParent->FlatBuffer() + DATA_OFFSET; uint8 *location = fParent->FlatBuffer() + DATA_OFFSET;
for (int32 index = 0; index < fHeader->count; index++) { for (int32 index = 0; index < header->count; index++) {
ItemInfo *info = new ItemInfo(offset); ItemInfo *info = new ItemInfo(offset);
info->length = *(size_t *)location; info->length = *(size_t *)location;
info->paddedLength = round_to_8(info->length); info->paddedLength = round_to_8(info->length);
@ -86,25 +93,22 @@ BMessageField::Unflatten(int32 _offset)
location += info->paddedLength; location += info->paddedLength;
} }
return sizeof(FieldHeader) + fHeader->nameLength + offset; return fDataOffset + offset;
}
void
BMessageField::SetOffset(int32 offset)
{
fOffset = offset;
fHeader = (FieldHeader *)(fParent->FlatBuffer() + fOffset);
} }
void void
BMessageField::SetName(const char *newName) BMessageField::SetName(const char *newName)
{ {
FieldHeader *header = Header();
int32 newLength = min_c(strlen(newName), 254) + 1; int32 newLength = min_c(strlen(newName), 254) + 1;
char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader), fHeader->nameLength, newLength); char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader), header->nameLength, newLength);
strcpy(buffer, newName); strncpy(buffer, newName, newLength);
fHeader->nameLength = newLength; buffer[newLength] = 0;
header->nameLength = newLength;
fDataOffset = sizeof(FieldHeader) + newLength;
} }
@ -118,12 +122,13 @@ BMessageField::Name() const
status_t status_t
BMessageField::SetFixedSize(int32 itemSize) BMessageField::SetFixedSize(int32 itemSize)
{ {
if ((fItemSize > 0 && fItemSize != itemSize) if (fItemInfos.CountItems() > 0
|| fItemInfos.CountItems() > 0) && (fItemSize > 0 && fItemSize != itemSize))
return B_BAD_VALUE; return B_BAD_VALUE;
fItemSize = itemSize; fItemSize = itemSize;
fHeader->flags |= MSG_FLAG_FIXED_SIZE; Header()->flags |= MSG_FLAG_FIXED_SIZE;
fFixedSize = true;
return B_OK; return B_OK;
} }
@ -138,16 +143,18 @@ BMessageField::AddItem(const void *item, ssize_t length)
uint8 * uint8 *
BMessageField::AddItem(ssize_t length) BMessageField::AddItem(ssize_t length)
{ {
if (fHeader->flags & MSG_FLAG_FIXED_SIZE) { FieldHeader *header = Header();
int32 offset = DATA_OFFSET + (fHeader->count * fItemSize);
fHeader->dataSize += fItemSize; if (fFixedSize) {
fHeader->count++; int32 offset = DATA_OFFSET + (header->count * fItemSize);
header->dataSize += fItemSize;
header->count++;
return fParent->FlatInsert(offset, 0, fItemSize); return fParent->FlatInsert(offset, 0, fItemSize);
} }
int32 newOffset = 0; int32 newOffset = 0;
if (fHeader->count > 0) { if (header->count > 0) {
ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(fHeader->count - 1); ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(header->count - 1);
newOffset = info->offset + info->paddedLength; newOffset = info->offset + info->paddedLength;
} }
@ -155,8 +162,8 @@ BMessageField::AddItem(ssize_t length)
newInfo->paddedLength = round_to_8(length); newInfo->paddedLength = round_to_8(length);
fItemInfos.AddItem(newInfo); fItemInfos.AddItem(newInfo);
fHeader->dataSize += newInfo->paddedLength; header->dataSize += newInfo->paddedLength;
fHeader->count++; header->count++;
uint8 *result = fParent->FlatInsert(DATA_OFFSET + newInfo->offset, 0, newInfo->paddedLength); uint8 *result = fParent->FlatInsert(DATA_OFFSET + newInfo->offset, 0, newInfo->paddedLength);
*(int32 *)result = length; *(int32 *)result = length;
@ -174,7 +181,7 @@ BMessageField::ReplaceItem(int32 index, const void *newItem, ssize_t length)
uint8 * uint8 *
BMessageField::ReplaceItem(int32 index, ssize_t length) BMessageField::ReplaceItem(int32 index, ssize_t length)
{ {
if (fHeader->flags & MSG_FLAG_FIXED_SIZE) if (fFixedSize)
return fParent->FlatBuffer() + DATA_OFFSET + (index * fItemSize); return fParent->FlatBuffer() + DATA_OFFSET + (index * fItemSize);
ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(index); ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(index);
@ -187,10 +194,11 @@ BMessageField::ReplaceItem(int32 index, ssize_t length)
return result + sizeof(int32); return result + sizeof(int32);
} }
FieldHeader *header = Header();
int32 change = newLength - info->paddedLength; int32 change = newLength - info->paddedLength;
for (int32 i = index + 1; i < fHeader->count; i++) for (int32 i = index + 1; i < header->count; i++)
((ItemInfo *)fItemInfos.ItemAt(i))->offset += change; ((ItemInfo *)fItemInfos.ItemAt(i))->offset += change;
fHeader->dataSize += change; header->dataSize += change;
int32 oldLength = info->paddedLength; int32 oldLength = info->paddedLength;
info->length = length; info->length = length;
@ -205,7 +213,7 @@ BMessageField::ReplaceItem(int32 index, ssize_t length)
void * void *
BMessageField::ItemAt(int32 index, ssize_t *size) BMessageField::ItemAt(int32 index, ssize_t *size)
{ {
if (fHeader->flags & MSG_FLAG_FIXED_SIZE) { if (fFixedSize) {
if (size) if (size)
*size = fItemSize; *size = fItemSize;
@ -224,21 +232,23 @@ BMessageField::ItemAt(int32 index, ssize_t *size)
void void
BMessageField::RemoveItem(int32 index) BMessageField::RemoveItem(int32 index)
{ {
if (fHeader->flags & MSG_FLAG_FIXED_SIZE) { FieldHeader *header = Header();
if (fFixedSize) {
fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0); fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0);
fHeader->dataSize -= fItemSize; header->dataSize -= fItemSize;
fHeader->count--; header->count--;
return; return;
} }
ItemInfo *info = (ItemInfo *)fItemInfos.RemoveItem(index); ItemInfo *info = (ItemInfo *)fItemInfos.RemoveItem(index);
for (int32 i = index; i < fHeader->count; i++) for (int32 i = index; i < header->count; i++)
((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength; ((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength;
fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0); fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0);
fHeader->dataSize -= info->paddedLength; header->dataSize -= info->paddedLength;
fHeader->count--; header->count--;
delete info; delete info;
} }
@ -246,7 +256,8 @@ BMessageField::RemoveItem(int32 index)
void void
BMessageField::PrintToStream() const BMessageField::PrintToStream() const
{ {
printf("\tname: \"%s\"; items: %ld; dataSize: %ld; flags: %02x;", Name(), fHeader->count, fHeader->dataSize, fHeader->flags); FieldHeader *header = Header();
printf("\tname: \"%s\"; items: %ld; dataSize: %ld; flags: %02x; offset: %ld", Name(), header->count, header->dataSize, header->flags, fOffset);
// ToDo: implement for real // ToDo: implement for real
} }
@ -264,10 +275,10 @@ BMessageField::MakeEmpty()
void void
BMessageField::RemoveSelf() BMessageField::RemoveSelf()
{ {
// remove ourselfs from the flat buffer // remove ourself from the flat buffer
fParent->FlatInsert(fOffset, sizeof(FieldHeader) + fHeader->nameLength + fHeader->dataSize, 0); FieldHeader *header = Header();
fParent->FlatInsert(fOffset, fDataOffset + header->dataSize, 0);
fOffset = 0; fOffset = 0;
fHeader = NULL;
} }
} // namespace BPrivate } // namespace BPrivate