From f936fa126134f4633d7e95574a3d45cf1fd92ff5 Mon Sep 17 00:00:00 2001 From: ejakowatz Date: Tue, 2 Nov 2004 21:35:28 +0000 Subject: [PATCH] A number of bug fixes. In particular: - only one byte was being used for total data length in a data field which had 'maxi' size data (total data > 255 bytes), rather than the correct four bytes. - Seem to have finally nailed the proper algorithm for calculating data item padding (four size bytes + bytes of data, padded to 8-byte boundary) in all places. - Was passing the address of the padding string, rather than the string itself, when writing out NULL padding bytes - Was incorrectly clearing the MSG_FLAG_MINI_DATA bit when the number of data items or the size of the largest data item exceeding 256 bytes. Bit is now cleared when total size of all item data (including size bytes and padding, if applicable) exceeds 256 bytes - Modified SizePolicy::Padding(const T&) to use calc_padding() from MessageUtils.h/.cpp - Added SizePolicy::Padding(const Store&) to calculate padding for data field's entire data store git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9743 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/app/MessageField.h | 126 +++++++++++++++++++++-------- 1 file changed, 91 insertions(+), 35 deletions(-) diff --git a/headers/private/app/MessageField.h b/headers/private/app/MessageField.h index 9b45453424..9b20d8677c 100644 --- a/headers/private/app/MessageField.h +++ b/headers/private/app/MessageField.h @@ -44,6 +44,7 @@ // Project Includes ------------------------------------------------------------ #include +#include // Local Includes -------------------------------------------------------------- @@ -127,6 +128,7 @@ struct BMessageFieldSizePolicy } inline static bool Fixed() { return true; } inline static size_t Padding(const T&) { return 0; } + inline static size_t Padding(const Store& data) { return 0; } }; //------------------------------------------------------------------------------ template @@ -220,23 +222,38 @@ FlattenedSize() const ssize_t size = 1; // field flags byte size += sizeof (type_code); // field type bytes if (!(fFlags & MSG_FLAG_SINGLE_ITEM)) // item count byte - ++size; + { + if (fFlags & MSG_FLAG_MINI_DATA) + ++size; // item count byte for mini data + else + size += 4; // item count bytes for maxi data + } + 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 += 4; // data length bytes for maxi data + ++size; // name length byte size += Name().length(); // name length - // data length and item size bytes + // item data length size += SizePolicy::Size(fData); + + // Calculate any necessary padding if (!SizePolicy::Fixed()) { + size += 4 * fData.Size(); + size += SizePolicy::Padding(fData); +#if 0 for (uint32 i = 0; i < fData.Size(); ++i) { - size += SizePolicy::Padding(fData[i]); // pad to 8-byte boundary - size += 4; // item size bytes + // pad to 8-byte boundary, including size bytes in calculation + size += calc_padding(SizePolicy::Size(fData[i]) + 4, 8); + // item size bytes + size += 4; } +#endif } return size; @@ -257,20 +274,10 @@ Flatten(BDataIO& stream) const { status_t err = B_OK; type_code type = Type(); - uint8 count = fData.Size(); + uint32 count = fData.Size(); 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, sizeof (fFlags)); // Field type_code @@ -279,11 +286,27 @@ Flatten(BDataIO& stream) const // Item count, if more than one if (err >= 0 && !(fFlags & MSG_FLAG_SINGLE_ITEM)) - err = stream.Write(&count, sizeof (count)); + { + if (fFlags & MSG_FLAG_MINI_DATA) + { + uint8 miniCount = count; + err = stream.Write(&miniCount, sizeof (miniCount)); + } + else + { + err = stream.Write(&count, sizeof (count)); + } + } // Data length if (err >= 0) { + if (!(fFlags & MSG_FLAG_FIXED_SIZE)) + { + // Add the bytes for holding the item size for each item + size += 4 * fData.Size(); + size += SizePolicy::Padding(fData); + } if (fFlags & MSG_FLAG_MINI_DATA) { uint8 miniSize = size; @@ -308,16 +331,17 @@ Flatten(BDataIO& stream) const { if (!SizePolicy::Fixed()) { - int32 size = (int32)SizePolicy::Size(fData[i]); + size = (int32)SizePolicy::Size(fData[i]); err = stream.Write(&size, sizeof (size)); } if (err >= 0) { err = FlattenPolicy::Flatten(stream, fData[i]); } - if (err >= 0) + if (err >= 0 && !SizePolicy::Fixed()) { - err = stream.Write(&BMessageField::sNullData[size], + // Add any necessary padding + err = stream.Write(BMessageField::sNullData, SizePolicy::Padding(fData[i])); } } @@ -361,8 +385,17 @@ AddItem(const T1& data) fMaxSize = SizePolicy::Size(data); } - if (fData.Size() > 256 || fMaxSize > 256) - fFlags &= ~MSG_FLAG_MINI_DATA; + if (fFlags & MSG_FLAG_MINI_DATA) + { + int32 size = SizePolicy::Size(fData); + if (!(fFlags & MSG_FLAG_FIXED_SIZE)) + { + size += 4 * fData.Size(); + size += SizePolicy::Padding(fData); + } + if (size > 255) + fFlags &= ~MSG_FLAG_MINI_DATA; + } if (fData.Size() > 1) fFlags &= ~MSG_FLAG_SINGLE_ITEM; @@ -587,18 +620,25 @@ template<> struct BMessageFieldSizePolicy { 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) + // Padding calculations are only done for variable-sized items, + // which by definition have four bytes of size info preceeding the + // actual data; those four bytes are included in the padding + // calculation. Padding is calculated to an 8-byte boundary + return calc_padding(Size(s) + 4, 8); + } + inline static size_t Padding(const Store& data) + { + size_t size = 0; + for (uint32 i = 0; i < data.Size(); ++i) { - temp = 8 - temp; + size += Padding(data[i]); } - return temp; + return size; } }; //------------------------------------------------------------------------------ @@ -621,12 +661,20 @@ template<> struct BMessageFieldSizePolicy inline static bool Fixed() { return false; } inline static size_t Padding(const BDataBuffer& db) { - size_t temp = (Size(db) + 4) % 8; - if (temp) + // Padding calculations are only done for variable-sized items, + // which by definition have four bytes of size info preceeding the + // actual data; those four bytes are included in the padding + // calculation. Padding is calculated to an 8-byte boundary + return calc_padding(Size(db) + 4, 8); + } + inline static size_t Padding(const Store& data) + { + size_t size = 0; + for (uint32 i = 0; i < data.Size(); ++i) { - temp = 8 - temp; + size += Padding(data[i]); } - return temp; + return size; } }; //------------------------------------------------------------------------------ @@ -649,12 +697,20 @@ template<> struct BMessageFieldSizePolicy inline static bool Fixed() { return false; } inline static size_t Padding(const BMessage* msg) { - size_t temp = (Size(msg) + 4) % 8; - if (temp) + // Padding calculations are only done for variable-sized items, + // which by definition have four bytes of size info preceeding the + // actual data; those four bytes are included in the padding + // calculation. Padding is calculated to an 8-byte boundary + return calc_padding(Size(msg) + 4, 8); + } + inline static size_t Padding(const Store& data) + { + size_t size = 0; + for (uint32 i = 0; i < data.Size(); ++i) { - temp = 8 - temp; + size += Padding(data[i]); } - return temp; + return size; } }; // Flatten policy specializations ----------------------------------------------