diff --git a/headers/private/app/MessageBody2.h b/headers/private/app/MessageBody2.h index 5891bf0e24..5be5bb64c5 100644 --- a/headers/private/app/MessageBody2.h +++ b/headers/private/app/MessageBody2.h @@ -43,7 +43,7 @@ public: status_t Flatten(BDataIO *stream) const; status_t Unflatten(BDataIO *stream); - status_t AddData(const char *name, BMallocIO *buffer, + status_t AddData(const char *name, BSimpleMallocIO *buffer, type_code type); status_t RemoveData(const char *name, int32 index = 0); @@ -52,7 +52,7 @@ public: int32 index, const void **data, ssize_t *numBytes) const; status_t ReplaceData(const char *name, int32 index, - BMallocIO *buffer, type_code type); + BSimpleMallocIO *buffer, type_code type); status_t Rename(const char *oldName, const char *newName); status_t RemoveName(const char *name); @@ -77,6 +77,8 @@ private: BList fFieldList; BMessageField **fFieldTable; int32 fFieldTableSize; + +mutable ssize_t fFlattenedSize; }; } // namespace BPrivate diff --git a/headers/private/app/MessageField2.h b/headers/private/app/MessageField2.h index 2a22dfc451..8e95f8df4a 100644 --- a/headers/private/app/MessageField2.h +++ b/headers/private/app/MessageField2.h @@ -25,6 +25,8 @@ namespace BPrivate { +class BSimpleMallocIO; + class BMessageField { public: BMessageField(); @@ -41,10 +43,9 @@ public: uint8 NameLength() const { return fName.Length(); }; type_code Type() const { return fType; }; - void AddItem(BMallocIO *item); - void ReplaceItem(int32 index, BMallocIO *item, - bool deleteOld = true); - void RemoveItem(int32 index, bool deleteIt = true); + void AddItem(BSimpleMallocIO *item); + void ReplaceItem(int32 index, BSimpleMallocIO *item); + void RemoveItem(int32 index); int32 CountItems() const { return fItems.CountItems(); }; size_t SizeAt(int32 index) const; const void *BufferAt(int32 index) const; diff --git a/headers/private/app/MessageUtils2.h b/headers/private/app/MessageUtils2.h index 431a7deb67..1087ba2aad 100644 --- a/headers/private/app/MessageUtils2.h +++ b/headers/private/app/MessageUtils2.h @@ -116,15 +116,14 @@ public: if (fError < B_OK) throw fError; - if (IsSwapping()) { + if (IsSwapping()) byte_swap(data); - } } template inline void operator()(T data, size_t len) { - fError = fStream->Read((void*)data, len); + fError = fStream->Read((void *)data, len); if (fError < B_OK) throw fError; } diff --git a/headers/private/app/SimpleMallocIO.h b/headers/private/app/SimpleMallocIO.h new file mode 100644 index 0000000000..08186654d4 --- /dev/null +++ b/headers/private/app/SimpleMallocIO.h @@ -0,0 +1,88 @@ +/* + * Copyright 2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +/* A BMallocIO similar structure but with less overhead */ + +#ifndef _SIMPLE_MALLOC_IO_H_ +#define _SIMPLE_MALLOC_IO_H_ + +#include + +namespace BPrivate { + +class BSimpleMallocIO { +public: + BSimpleMallocIO(size_t size) + : fSize(size) + { + fBuffer = (char *)malloc(size); + } + + ~BSimpleMallocIO() + { + free(fBuffer); + } + + void Read(void *buffer) + { + memcpy(buffer, fBuffer, fSize); + } + + void Read(void *buffer, size_t size) + { + memcpy(buffer, fBuffer, size); + } + + void ReadAt(off_t pos, void *buffer, size_t size) + { + memcpy(buffer, fBuffer + pos, size); + } + + void Write(const void *buffer) + { + memcpy(fBuffer, buffer, fSize); + } + + void Write(const void *buffer, size_t size) + { + memcpy(fBuffer, buffer, size); + } + + void WriteAt(off_t pos, const void *buffer, size_t size) + { + memcpy(fBuffer + pos, buffer, size); + } + + status_t SetSize(off_t size) + { + fBuffer = (char *)realloc(fBuffer, size); + if (!fBuffer) + return B_NO_MEMORY; + + fSize = size; + return B_OK; + } + + char *Buffer() + { + return fBuffer; + } + + size_t BufferLength() + { + return fSize; + } + +private: + char *fBuffer; + size_t fSize; +}; + +} // namespace BPivate + +#endif // _SIMPLE_MALLOC_IO_H_ diff --git a/src/kits/app/Message2.cpp b/src/kits/app/Message2.cpp index a1d7ff0f57..8ffde92446 100644 --- a/src/kits/app/Message2.cpp +++ b/src/kits/app/Message2.cpp @@ -34,11 +34,12 @@ #include #include -#include #include #include "MessageBody2.h" #include "MessageField2.h" +#include "MessageUtils2.h" +#include "SimpleMallocIO.h" #include "dano_message.h" // flags for the overall message (the bitfield is 1 byte) @@ -873,9 +874,6 @@ BMessage::Unflatten(BDataIO *stream) header.WriteTo(*this); status = fBody->Unflatten(stream); - if (status < B_OK) - return status; - } catch (status_t &error) { status = error; } @@ -1152,11 +1150,9 @@ BMessage::AddMessenger(const char *name, BMessenger messenger) status_t BMessage::AddRef(const char* name, const entry_ref* ref) { - BMallocIO *buffer = new BMallocIO(); - buffer->SetSize(sizeof(entry_ref) + B_PATH_NAME_LENGTH); - - size_t size; - status_t error = entry_ref_flatten((char *)buffer->Buffer(), &size, ref); + size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref); buffer->SetSize(size); if (error >= B_OK) @@ -1172,8 +1168,9 @@ BMessage::AddRef(const char* name, const entry_ref* ref) status_t BMessage::AddMessage(const char *name, const BMessage *msg) { - BMallocIO *buffer = new BMallocIO(); - status_t error = msg->Flatten(buffer); + size_t size = msg->FlattenedSize(); + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = msg->Flatten(buffer->Buffer(), size); if (error >= B_OK) error = fBody->AddData(name, buffer, B_MESSAGE_TYPE); @@ -1189,10 +1186,9 @@ status_t BMessage::AddFlat(const char *name, BFlattenable *object, int32 count) { ssize_t size = object->FlattenedSize(); - BMallocIO *buffer = new BMallocIO(); - buffer->SetSize(size); + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = object->Flatten(buffer->Buffer(), size); - status_t error = object->Flatten((void *)buffer->Buffer(), size); if (error >= B_OK) error = fBody->AddData(name, buffer, object->TypeCode()); @@ -1212,8 +1208,8 @@ BMessage::AddData(const char *name, type_code type, const void *data, // the user attempts to add something bigger or smaller. We may need to // enforce the size thing. - BMallocIO *buffer = new BMallocIO(); - buffer->Write(data, numBytes); + BSimpleMallocIO *buffer = new BSimpleMallocIO(numBytes); + buffer->Write(data); status_t error = fBody->AddData(name, buffer, type); if (error < B_OK) @@ -1364,7 +1360,7 @@ BMessage::FindMessage(const char *name, int32 index, BMessage *msg) const status_t error = FindData(name, B_MESSAGE_TYPE, index, (const void **)&data, &size); if (!error) - error = msg->Unflatten((const char*)data); + error = msg->Unflatten((const char *)data); else *msg = BMessage(); @@ -1493,11 +1489,9 @@ BMessage::ReplaceRef(const char *name, const entry_ref *ref) status_t BMessage::ReplaceRef(const char *name, int32 index, const entry_ref *ref) { - BMallocIO *buffer = new BMallocIO(); - buffer->SetSize(sizeof(entry_ref) + B_PATH_NAME_LENGTH); - - size_t size; - status_t error = entry_ref_flatten((char *)buffer->Buffer(), &size, ref); + size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref); buffer->SetSize(size); if (error >= B_OK) @@ -1520,8 +1514,9 @@ BMessage::ReplaceMessage(const char *name, const BMessage *msg) status_t BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *msg) { - BMallocIO *buffer = new BMallocIO(); - status_t error = msg->Flatten(buffer); + size_t size = msg->FlattenedSize(); + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = msg->Flatten(buffer->Buffer(), size); if (error >= B_OK) error = fBody->ReplaceData(name, index, buffer, B_MESSAGE_TYPE); @@ -1544,10 +1539,9 @@ status_t BMessage::ReplaceFlat(const char *name, int32 index, BFlattenable *object) { ssize_t size = object->FlattenedSize(); - BMallocIO *buffer = new BMallocIO(); - buffer->SetSize(size); + BSimpleMallocIO *buffer = new BSimpleMallocIO(size); + status_t error = object->Flatten(buffer->Buffer(), size); - status_t error = object->Flatten((void *)buffer->Buffer(), size); if (error >= B_OK) error = fBody->ReplaceData(name, index, buffer, object->TypeCode()); @@ -1570,8 +1564,8 @@ status_t BMessage::ReplaceData(const char *name, type_code type, int32 index, const void *data, ssize_t data_size) { - BMallocIO *buffer = new BMallocIO(); - buffer->Write(data, data_size); + BSimpleMallocIO *buffer = new BSimpleMallocIO(data_size); + buffer->Write(data); status_t error = fBody->ReplaceData(name, index, buffer, type); if (error < B_OK) @@ -1629,7 +1623,7 @@ BMessage::operator delete(void *ptr, size_t size) status_t BMessage::real_flatten(char *result, ssize_t size) const { - BMemoryIO stream((void*)result, size); + BMemoryIO stream((void *)result, size); return real_flatten(&stream, NULL); } @@ -1640,9 +1634,12 @@ BMessage::real_flatten(BDataIO *stream, ssize_t *size) const Header header(*this); status_t error = header.WriteTo(*stream); - if (!error) + if (error >= B_OK) error = fBody->Flatten(stream); + if (size) + *size = FlattenedSize(); + return error; } @@ -1686,14 +1683,14 @@ BMessage::calc_hdr_size(uchar flags) const ssize_t size = min_hdr_size(); if (fTarget != B_NULL_TOKEN) - size += sizeof (fTarget); + size += sizeof(fTarget); if (fReplyTo.port >= 0 && fReplyTo.target != B_NULL_TOKEN && fReplyTo.team >= 0) { - size += sizeof (fReplyTo.port); - size += sizeof (fReplyTo.target); - size += sizeof (fReplyTo.team); + size += sizeof(fReplyTo.port); + size += sizeof(fReplyTo.target); + size += sizeof(fReplyTo.team); size += 4; // For the "big" flags } diff --git a/src/kits/app/MessageBody2.cpp b/src/kits/app/MessageBody2.cpp index ba32801ffd..b1f5096011 100644 --- a/src/kits/app/MessageBody2.cpp +++ b/src/kits/app/MessageBody2.cpp @@ -9,14 +9,17 @@ /* BMessageBody handles data storage and retrieval for BMessage. */ #include -#include -#include #include #include "MessageBody2.h" +#include "MessageUtils2.h" +#include "SimpleMallocIO.h" namespace BPrivate { static int64 sPadding[2] = { 0, 0 }; +static uint8 sPadLengths[8] = { 4, 3, 2, 1, 0, 7, 6, 5 }; + +#define CALC_PADDING_8(x) sPadLengths[x % 8] BMessageBody::BMessageBody() { @@ -59,6 +62,7 @@ BMessageBody::operator=(const BMessageBody &other) status_t BMessageBody::InitCommon() { + fFlattenedSize = -1; fFieldTableSize = 100; fFieldTable = new BMessageField *[fFieldTableSize]; HashClear(); @@ -201,6 +205,7 @@ BMessageBody::Rename(const char *oldName, const char *newName) field->SetName(newName); HashInsert(HashRemove(oldName)); + fFlattenedSize = -1; return B_OK; } @@ -208,6 +213,9 @@ BMessageBody::Rename(const char *oldName, const char *newName) ssize_t BMessageBody::FlattenedSize() const { + if (fFlattenedSize > 0) + return fFlattenedSize; + ssize_t size = 1; // for MSG_LAST_ENTRY for (int32 index = 0; index < fFieldList.CountItems(); index++) { @@ -233,15 +241,12 @@ BMessageBody::FlattenedSize() const // name length byte and name length size += 1 + field->NameLength(); - // individual sizes - if (!(flags & MSG_FLAG_FIXED_SIZE)) { - size += field->CountItems() * sizeof(size_t); - size += field->TotalPadding(); - } - size += field->TotalSize(); } + // cache the value for next time. + // changing the body will reset this. + fFlattenedSize = size; return size; } @@ -249,8 +254,6 @@ BMessageBody::FlattenedSize() const status_t BMessageBody::Flatten(BDataIO *stream) const { - status_t error = B_OK; - for (int32 index = 0; index < fFieldList.CountItems(); index++) { BMessageField *field = (BMessageField *)fFieldList.ItemAt(index); @@ -270,16 +273,8 @@ BMessageBody::Flatten(BDataIO *stream) const stream->Write(&count, sizeof(count)); } - bool isFixed = flags & MSG_FLAG_FIXED_SIZE; - - // overall data size + // overall data size (includes padding for non fixed size fields) size_t size = field->TotalSize(); - if (!isFixed) { - // add bytes for holding each items size - size += count * sizeof(size_t); - size += field->TotalPadding(); - } - if (flags & MSG_FLAG_MINI_DATA) { uint8 miniSize = (uint8)size; stream->Write(&miniSize, sizeof(miniSize)); @@ -293,32 +288,29 @@ BMessageBody::Flatten(BDataIO *stream) const // name stream->Write(field->Name(), nameLength); - // if we have a fixed size we initialize size once here - if (isFixed) - size = field->SizeAt(0); - // data items - for (int32 dataIndex = 0; dataIndex < count; dataIndex++) { - if (!isFixed) { - // set the size for each item + if (flags & MSG_FLAG_FIXED_SIZE) { + size = field->SizeAt(0); + for (int32 dataIndex = 0; dataIndex < count; dataIndex++) + stream->Write(field->BufferAt(dataIndex), size); + } else { + for (int32 dataIndex = 0; dataIndex < count; dataIndex++) { size = field->SizeAt(dataIndex); stream->Write(&size, sizeof(size)); + + stream->Write(field->BufferAt(dataIndex), size); + size_t error = stream->Write(sPadding, CALC_PADDING_8(size)); } - - error = stream->Write(field->BufferAt(dataIndex), size); - - if (!isFixed) - error = stream->Write(sPadding, calc_padding(size + 4, 8)); } } - if (error >= B_OK) { - uint8 lastEntry = 0; - error = stream->Write(&lastEntry, sizeof(lastEntry)); - } + uint8 lastEntry = 0; + size_t error = stream->Write(&lastEntry, sizeof(lastEntry)); - if (error >= B_OK) + if (error > B_OK) return B_OK; + else if (error == 0) + return B_ERROR; return error; } @@ -344,6 +336,7 @@ BMessageBody::Unflatten(BDataIO *stream) int32 itemCount; int32 dataLength; uint8 littleData; + if (flags & MSG_FLAG_SINGLE_ITEM) { itemCount = 1; @@ -398,9 +391,8 @@ BMessageBody::Unflatten(BDataIO *stream) int32 itemSize = dataLength / itemCount; for (int32 index = 0; index < itemCount; index++) { - BMallocIO *buffer = new BMallocIO(); - buffer->SetSize(itemSize); - reader((char *)buffer->Buffer(), itemSize); + BSimpleMallocIO *buffer = new BSimpleMallocIO(itemSize); + reader(buffer->Buffer(), itemSize); field->AddItem(buffer); } } else { @@ -408,12 +400,10 @@ BMessageBody::Unflatten(BDataIO *stream) ssize_t dataLength; for (int32 index = 0; index < itemCount; index++) { - BMallocIO *buffer = new BMallocIO(); reader(dataLength); - buffer->SetSize(dataLength); - - reader((char *)buffer->Buffer(), dataLength); - reader(padding, calc_padding(dataLength + 4, 8)); + BSimpleMallocIO *buffer = new BSimpleMallocIO(dataLength); + reader(buffer->Buffer(), dataLength); + reader(padding, CALC_PADDING_8(dataLength)); field->AddItem(buffer); } } @@ -429,7 +419,7 @@ BMessageBody::Unflatten(BDataIO *stream) status_t -BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type) +BMessageBody::AddData(const char *name, BSimpleMallocIO *buffer, type_code type) { status_t error = B_OK; BMessageField *foundField = FindData(name, type, error); @@ -457,6 +447,7 @@ BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type) foundField->AddItem(buffer); } + fFlattenedSize = -1; return error; } @@ -485,7 +476,7 @@ BMessageBody::AddField(const char *name, type_code type, status_t &error) status_t -BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer, +BMessageBody::ReplaceData(const char *name, int32 index, BSimpleMallocIO *buffer, type_code type) { if (type == B_ANY_TYPE) @@ -501,6 +492,7 @@ BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer, return B_ERROR; field->ReplaceItem(index, buffer); + fFlattenedSize = -1; return error; } @@ -508,9 +500,8 @@ BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer, status_t BMessageBody::RemoveData(const char *name, int32 index) { - if (index < 0) { + if (index < 0) return B_BAD_VALUE; - } status_t error = B_OK; BMessageField *field = FindData(name, B_ANY_TYPE, error); @@ -518,10 +509,10 @@ BMessageBody::RemoveData(const char *name, int32 index) if (field) { if (index < field->CountItems()) { field->RemoveItem(index); + fFlattenedSize = -1; - if (field->CountItems() == 0) { + if (field->CountItems() == 0) RemoveName(name); - } } else error = B_BAD_INDEX; } @@ -538,6 +529,7 @@ BMessageBody::RemoveName(const char *name) if (field) { fFieldList.RemoveItem(field); + fFlattenedSize = -1; HashRemove(name); delete field; } @@ -555,6 +547,7 @@ BMessageBody::MakeEmpty() } fFieldList.MakeEmpty(); + fFlattenedSize = -1; HashClear(); return B_OK; } diff --git a/src/kits/app/MessageField2.cpp b/src/kits/app/MessageField2.cpp index 5fd50eab17..40acd73c7c 100644 --- a/src/kits/app/MessageField2.cpp +++ b/src/kits/app/MessageField2.cpp @@ -7,18 +7,18 @@ */ #include -#include -#include #include #include "MessageField2.h" +#include "SimpleMallocIO.h" namespace BPrivate { +#define ROUND_TO_8(x) (fFixedSize ? x : (x + 11) & ~7) + BMessageField::BMessageField() : fType(0), fFixedSize(false), fTotalSize(0), - fTotalPadding(0), fNext(NULL) { SetName(""); @@ -28,7 +28,6 @@ BMessageField::BMessageField() BMessageField::BMessageField(const char *name, type_code type) : fType(type), fTotalSize(0), - fTotalPadding(0), fNext(NULL) { SetName(name); @@ -58,13 +57,12 @@ BMessageField::operator=(const BMessageField &other) fType = other.fType; fFixedSize = other.fFixedSize; fTotalSize = other.fTotalSize; - fTotalPadding = other.fTotalPadding; fNext = NULL; for (int32 index = 0; index < other.fItems.CountItems(); index++) { - BMallocIO *otherBuffer = (BMallocIO *)other.fItems.ItemAt(index); - BMallocIO *newBuffer = new BMallocIO; - newBuffer->Write(otherBuffer->Buffer(), otherBuffer->BufferLength()); + BSimpleMallocIO *otherBuffer = (BSimpleMallocIO *)other.fItems.ItemAt(index); + BSimpleMallocIO *newBuffer = new BSimpleMallocIO(otherBuffer->BufferLength()); + newBuffer->Write(otherBuffer->Buffer()); fItems.AddItem((void *)newBuffer); } } @@ -77,7 +75,7 @@ void BMessageField::MakeEmpty() { for (int32 index = 0; index < fItems.CountItems(); index++) { - BMallocIO *item = (BMallocIO *)fItems.ItemAt(index); + BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.ItemAt(index); delete item; } @@ -89,11 +87,11 @@ uint8 BMessageField::Flags() { uint8 flags = MSG_FLAG_VALID; - + if (fItems.CountItems() == 1) flags |= MSG_FLAG_SINGLE_ITEM; - if (fTotalSize + fTotalPadding < 255) + if (fTotalSize < 255) flags |= MSG_FLAG_MINI_DATA; if (fFixedSize) @@ -115,46 +113,39 @@ BMessageField::SetName(const char *name) void -BMessageField::AddItem(BMallocIO *item) +BMessageField::AddItem(BSimpleMallocIO *item) { fItems.AddItem((void *)item); - fTotalSize += item->BufferLength(); - fTotalPadding += calc_padding(item->BufferLength() + 4, 8); + fTotalSize += ROUND_TO_8(item->BufferLength()); } void -BMessageField::ReplaceItem(int32 index, BMallocIO *item, bool deleteOld) +BMessageField::ReplaceItem(int32 index, BSimpleMallocIO *item) { - BMallocIO *oldItem = (BMallocIO *)fItems.ItemAt(index); - fTotalSize -= oldItem->BufferLength(); - fTotalPadding -= calc_padding(oldItem->BufferLength() + 4, 8); - + BSimpleMallocIO *oldItem = (BSimpleMallocIO *)fItems.ItemAt(index); fItems.ReplaceItem(index, item); - fTotalSize += item->BufferLength(); - fTotalPadding += calc_padding(item->BufferLength() + 4, 8); - if (deleteOld) - delete oldItem; + fTotalSize -= ROUND_TO_8(oldItem->BufferLength()); + fTotalSize += ROUND_TO_8(item->BufferLength()); + + delete oldItem; } void -BMessageField::RemoveItem(int32 index, bool deleteIt) +BMessageField::RemoveItem(int32 index) { - BMallocIO *item = (BMallocIO *)fItems.RemoveItem(index); - - fTotalSize -= item->BufferLength(); - fTotalPadding -= calc_padding(item->BufferLength() + 4, 8); - if (deleteIt) - delete item; + BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.RemoveItem(index); + fTotalSize -= ROUND_TO_8(item->BufferLength()); + delete item; } size_t BMessageField::SizeAt(int32 index) const { - BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index); + BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index); if (buffer) return buffer->BufferLength(); @@ -166,7 +157,7 @@ BMessageField::SizeAt(int32 index) const const void * BMessageField::BufferAt(int32 index) const { - BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index); + BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index); if (buffer) return buffer->Buffer();