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_
#include <List.h>
#include "MessageField3.h"
enum {
B_FLATTENABLE_TYPE = 'FLAT'
@ -20,6 +19,8 @@ enum {
namespace BPrivate {
class BMessageField;
class BMessageBody {
public:
BMessageBody();
@ -68,7 +69,7 @@ public:
void PrintToStream() const;
// 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,
ssize_t newLength);

View File

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

View File

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

View File

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

View File

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