From 90dc946130450e4a71822a9bf99d15a7de571653 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 9 Aug 2005 05:49:13 +0000 Subject: [PATCH] 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 --- headers/private/app/MessageBody3.h | 5 +- headers/private/app/MessageField3.h | 23 +++-- src/kits/app/Message3.cpp | 10 ++- src/kits/app/MessageBody3.cpp | 4 +- src/kits/app/MessageField3.cpp | 129 +++++++++++++++------------- 5 files changed, 92 insertions(+), 79 deletions(-) diff --git a/headers/private/app/MessageBody3.h b/headers/private/app/MessageBody3.h index b37faab094..c66aee4683 100644 --- a/headers/private/app/MessageBody3.h +++ b/headers/private/app/MessageBody3.h @@ -12,7 +12,6 @@ #define _MESSAGE_BODY_H_ #include -#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); diff --git a/headers/private/app/MessageField3.h b/headers/private/app/MessageField3.h index 8afa68ee1a..c437db5c2d 100644 --- a/headers/private/app/MessageField3.h +++ b/headers/private/app/MessageField3.h @@ -14,6 +14,7 @@ #include #include #include +#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; diff --git a/src/kits/app/Message3.cpp b/src/kits/app/Message3.cpp index 198d3cf308..8ca3e09f7e 100644 --- a/src/kits/app/Message3.cpp +++ b/src/kits/app/Message3.cpp @@ -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)); \ diff --git a/src/kits/app/MessageBody3.cpp b/src/kits/app/MessageBody3.cpp index 5a3d52465f..a36fe8e576 100644 --- a/src/kits/app/MessageBody3.cpp +++ b/src/kits/app/MessageBody3.cpp @@ -12,6 +12,7 @@ #include #include #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(); diff --git a/src/kits/app/MessageField3.cpp b/src/kits/app/MessageField3.cpp index 8ff80272aa..ec022bd978 100644 --- a/src/kits/app/MessageField3.cpp +++ b/src/kits/app/MessageField3.cpp @@ -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