From 0784fd8bdeea7feb87aece44b126a7f8fdd62466 Mon Sep 17 00:00:00 2001 From: ejakowatz Date: Fri, 29 Aug 2003 22:32:22 +0000 Subject: [PATCH] Fixed bugs in (un)flattening code. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4403 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/app/MessageField.h | 163 ++++++++++++++++++----------- src/kits/app/MessageBody.cpp | 2 +- 2 files changed, 105 insertions(+), 60 deletions(-) diff --git a/headers/private/app/MessageField.h b/headers/private/app/MessageField.h index f432852f5b..9a5b94ef7f 100644 --- a/headers/private/app/MessageField.h +++ b/headers/private/app/MessageField.h @@ -123,6 +123,7 @@ struct BMessageFieldSizePolicy return sizeof (T) * data.Size(); } inline static bool Fixed() { return true; } + inline static size_t Padding(const T&) { return 0; } }; //------------------------------------------------------------------------------ template @@ -209,18 +210,28 @@ ssize_t BMessageFieldImpl:: FlattenedSize() const { - ssize_t size = 0; - // Mandatory stuff - size += 1; // field flags byte + ssize_t size = 1; // field flags byte size += sizeof (type_code); // field type bytes if (!(fFlags & MSG_FLAG_SINGLE_ITEM)) // item count byte ++size; - ++size; // data length byte + if (fFlags & MSG_FLAG_MINI_DATA) + ++size; // data length byte for mini data + else + size += sizeof (size_t); // data length bytes for maxi data ++size; // name length byte size += Name().length(); // name length - size += SizePolicy::Size(fData); // data length and item size bytes + // data length and item size bytes + size += SizePolicy::Size(fData); + if (!SizePolicy::Fixed()) + { + for (uint32 i = 0; i < fData.Size(); ++i) + { + size += SizePolicy::Padding(fData[i]); // pad to 8-byte boundary + size += 4; // item size bytes + } + } return size; } @@ -241,10 +252,20 @@ Flatten(BDataIO& stream) const status_t err = B_OK; type_code type = Type(); uint8 count = fData.Size(); - uint8 size = SizePolicy::Size(fData); uint8 nameLen = Name().length(); + size_t size = SizePolicy::Size(fData); + + // Calculate any necessary padding + if (!SizePolicy::Fixed()) + { + for (uint32 i = 0; i < fData.Size(); ++i) + { + size += SizePolicy::Padding(fData[i]); // pad to 8-byte boundary + size += 4; // item size bytes + } + } - err = stream.Write(&fFlags, 1); + err = stream.Write(&fFlags, sizeof (fFlags)); // Field type_code if (err >= 0) @@ -252,15 +273,25 @@ Flatten(BDataIO& stream) const // Item count, if more than one if (err >= 0 && !(fFlags & MSG_FLAG_SINGLE_ITEM)) - err = stream.Write(&count, 1); + err = stream.Write(&count, sizeof (count)); // Data length if (err >= 0) - err = stream.Write(&size, 1); + { + if (fFlags & MSG_FLAG_MINI_DATA) + { + uint8 miniSize = size; + err = stream.Write(&miniSize, sizeof (miniSize)); + } + else + { + err = stream.Write(&size, sizeof (size)); + } + } // Name length if (err >= 0) - err = stream.Write(&nameLen, 1); + err = stream.Write(&nameLen, sizeof (nameLen)); // Name if (err >= 0) @@ -269,7 +300,20 @@ Flatten(BDataIO& stream) const // Actual data items for (uint32 i = 0; i < fData.Size() && err >= 0; ++i) { - err = FlattenPolicy::Flatten(stream, fData[i]); + if (!SizePolicy::Fixed()) + { + int32 size = (int32)SizePolicy::Size(fData[i]); + err = stream.Write(&size, sizeof (size)); + } + if (err >= 0) + { + err = FlattenPolicy::Flatten(stream, fData[i]); + } + if (err >= 0) + { + err = stream.Write(&BMessageField::sNullData[size], + SizePolicy::Padding(fData[i])); + } } if (err >= 0) @@ -465,18 +509,23 @@ template<> struct BMessageFieldSizePolicy inline static size_t Size(const Store& data) { size_t size = 0; - size_t temp; for (uint32 i = 0; i < data.Size(); ++i) { - temp = Size(data[i]) + 4; // Four extra bytes for size info - // Calculate padding - temp += 8 - (temp % 8); - size += temp; + size += Size(data[i]); } return size; } inline static bool Fixed() { return false; } + inline static size_t Padding(const BString& s) + { + size_t temp = (Size(s) + 4) % 8; + if (temp) + { + temp = 8 - temp; + } + return temp; + } }; //------------------------------------------------------------------------------ template<> struct BMessageFieldSizePolicy @@ -488,18 +537,23 @@ template<> struct BMessageFieldSizePolicy inline static size_t Size(const Store& data) { size_t size = 0; - size_t temp; for (uint32 i = 0; i < data.Size(); ++i) { - temp = Size(data[i]) + 4; // Four extra bytes for size info - // Calculate padding - temp += 8 - (temp % 8); - size += temp; + size += Size(data[i]); } return size; } inline static bool Fixed() { return false; } + inline static size_t Padding(const BDataBuffer& db) + { + size_t temp = (Size(db) + 4) % 8; + if (temp) + { + temp = 8 - temp; + } + return temp; + } }; //------------------------------------------------------------------------------ template<> struct BMessageFieldSizePolicy @@ -511,18 +565,23 @@ template<> struct BMessageFieldSizePolicy inline static size_t Size(const Store& data) { size_t size = 0; - size_t temp; for (uint32 i = 0; i < data.Size(); ++i) { - temp = Size(data[i]) + 4; // Four extra bytes for size info - // Calculate padding - temp += 8 - (temp % 8); - size += temp; + size += Size(data[i]); } return size; } inline static bool Fixed() { return false; } + inline static size_t Padding(const BMessage* msg) + { + size_t temp = (Size(msg) + 4) % 8; + if (temp) + { + temp = 8 - temp; + } + return temp; + } }; // Flatten policy specializations ---------------------------------------------- template<> @@ -533,23 +592,9 @@ struct BMessageFieldFlattenPolicy static status_t Flatten(BDataIO& stream, const BString& data) { size_t size = SizePolicy::Size(data); - status_t err = stream.Write(&size, 4); - - if (err >= 0) - err = stream.Write((const void*)data.String(), size); + status_t err = stream.Write((const void*)data.String(), size); - if (err >= 0) - { - // Pad data to 8-byte boundary - size += 4; // Account for the stored size of size - size %= 8; - if (size) - { - err = stream.Write(&BMessageField::sNullData[size], 8 - (size)); - } - } - - if (err >= 0) + if (err > 0) err = B_OK; return err; } @@ -562,24 +607,24 @@ struct BMessageFieldFlattenPolicy static status_t Flatten(BDataIO& stream, const BMessage* data) { - size_t size = SizePolicy::Size(data); - status_t err = stream.Write(&size, 4); + status_t err = data->Flatten(&stream); - if (err >= 0) - err = data->Flatten(&stream); - - if (err >= 0) - { - // Pad data to 8-byte boundary - size += 4; // Account for the stored size of size - size %= 8; - if (size) - { - err = stream.Write(&BMessageField::sNullData[size], 8 - (size)); - } - } - - if (err >= 0) + if (err > 0) + err = B_OK; + return err; + } +}; +//------------------------------------------------------------------------------ +template<> +struct BMessageFieldFlattenPolicy +{ + typedef BMessageFieldSizePolicy SizePolicy; + + static status_t Flatten(BDataIO& stream, const BDataBuffer& db) + { + size_t size = SizePolicy::Size(db); + status_t err = stream.Write(db.Buffer(), size); + if (err > 0) err = B_OK; return err; } diff --git a/src/kits/app/MessageBody.cpp b/src/kits/app/MessageBody.cpp index df1657ea00..6773c8c401 100644 --- a/src/kits/app/MessageBody.cpp +++ b/src/kits/app/MessageBody.cpp @@ -179,7 +179,7 @@ bool BMessageBody::IsEmpty() const //------------------------------------------------------------------------------ void BMessageBody::PrintToStream() const { - // TODO: implement + // TODO: test for (TMsgDataMap::const_iterator i = fData.begin(); i != fData.end(); ++i) { i->second->PrintToStream(i->first.c_str());