From 5f9ebca64c8a7ed0c23f68481bdd4e7e003a7ae6 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 7 Nov 2005 01:39:34 +0000 Subject: [PATCH] Adapting the dano message reader to the documentation. Not really tested yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14738 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/app/dano_message.cpp | 221 +++++++++++++++++++++++++--------- src/kits/app/dano_message.h | 2 +- 2 files changed, 168 insertions(+), 55 deletions(-) diff --git a/src/kits/app/dano_message.cpp b/src/kits/app/dano_message.cpp index 3b69a5f700..3a4b05db21 100644 --- a/src/kits/app/dano_message.cpp +++ b/src/kits/app/dano_message.cpp @@ -16,35 +16,76 @@ #include -struct dano_header { - uint32 code; - int32 size; - uint32 what; - uint32 _unknown; +enum { + SECTION_MESSAGE_HEADER = 'FOB2', + SECTION_OFFSET_TABLE = 'STof', + SECTION_TARGET_INFORMATION = 'ENwh', + SECTION_SINGLE_ITEM_DATA = 'SGDa', + SECTION_FIXED_SIZE_ARRAY_DATA = 'FADa', + SECTION_VARIABLE_SIZE_ARRAY_DATA = 'VADa', + SECTION_SORTED_INDEX_TABLE = 'DXIn', + SECTION_END_OF_DATA = 'DDEn' }; -struct dano_field_header { - uint32 code; - int32 size; -}; -struct dano_field { - uint32 type; - int32 data_size; - uint8 name_size; - char name[0]; -} _PACKED; +typedef struct section_header_s { + uint32 code; + ssize_t size; + uint8 data[0]; +} SectionHeader; + + +typedef struct message_header_s { + int32 what; + int32 padding; +} MessageHeader; + + +typedef struct offset_table_s { + int32 indexTable; + int32 endOfData; + int64 padding; +} OffsetTable; + + +typedef struct single_item_s { + type_code type; + ssize_t itemSize; + uint8 nameLength; + char name[0]; +} _PACKED SingleItem; + + +typedef struct fixed_size_array_s { + type_code type; + ssize_t sizePerItem; + uint8 nameLength; + char name[0]; +} _PACKED FixedSizeArray; + + +typedef struct variable_size_array_s { + type_code type; + int32 padding; + uint8 nameLength; + char name[0]; +} _PACKED VariableSizeArray; + -static const uint32 kMessageFormat = 'FOB2'; static const uint32 kMessageFormatSwapped = '2BOF'; -static const uint32 kDataField = 'SGDa'; - -size_t -BPrivate::dano_message_size(const char* buffer) +inline int32 +pad_to_8(int32 value) { - dano_header* header = (dano_header*)buffer; + return (value + 7) & ~7; +} + + +ssize_t +BPrivate::dano_message_size(const char *buffer) +{ + SectionHeader *header = (SectionHeader *)buffer; if (header->code == kMessageFormatSwapped) return __swap_int32(header->size); @@ -54,7 +95,8 @@ BPrivate::dano_message_size(const char* buffer) status_t -BPrivate::unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& message) +BPrivate::unflatten_dano_message(uint32 magic, BDataIO &stream, + BMessage &message) { TReadHelper reader(&stream); message.MakeEmpty(); @@ -62,61 +104,132 @@ BPrivate::unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& messag if (magic == kMessageFormatSwapped) reader.SetSwap(true); - int32 size; + ssize_t size; reader(size); - reader(message.what); - int32 value; - reader(value); // unknown + MessageHeader header; + reader(header); + message.what = header.what; - size -= sizeof(dano_header); + size -= sizeof(SectionHeader) + sizeof(MessageHeader); int32 offset = 0; while (offset < size) { - dano_field_header fieldHeader; - reader(fieldHeader); -printf("field.code = %.4s (%lx), field.size = %ld\n", - (char*)&fieldHeader.code, fieldHeader.code, fieldHeader.size); + SectionHeader sectionHeader; + reader(sectionHeader); - if (fieldHeader.size + offset > size) + if (offset + sectionHeader.size > size) return B_BAD_DATA; - uint32 fieldSize = fieldHeader.size - sizeof(dano_field_header); - char* fieldBuffer = (char*)malloc(fieldSize); + ssize_t fieldSize = sectionHeader.size - sizeof(SectionHeader); + uint8 *fieldBuffer = (uint8 *)malloc(fieldSize); if (fieldBuffer == NULL) throw (status_t)B_NO_MEMORY; reader(fieldBuffer, fieldSize); - if (fieldHeader.code == kDataField) { - dano_field* field = (dano_field*)fieldBuffer; + switch (sectionHeader.code) { + case SECTION_OFFSET_TABLE: break; /* discard */ + case SECTION_TARGET_INFORMATION: break; /* discard */ + case SECTION_SORTED_INDEX_TABLE: break; /* discard */ + case SECTION_END_OF_DATA: break; /* discard */ - int32 dataOffset = sizeof(dano_field) + field->name_size + 1; - dataOffset = (dataOffset + 7) & ~7; - // padding + case SECTION_SINGLE_ITEM_DATA: { + SingleItem *field = (SingleItem *)fieldBuffer; - if (field->data_size + dataOffset + offset > size) - return B_BAD_DATA; + int32 dataOffset = sizeof(SingleItem) + field->nameLength + 1; + dataOffset = pad_to_8(dataOffset); - // ToDo: support fixed size for real - bool fixedSize = true; - if (field->type == B_STRING_TYPE) - fixedSize = false; + if (offset + dataOffset + field->itemSize > size) + return B_BAD_DATA; - status_t status = message.AddData(field->name, field->type, - fieldBuffer + dataOffset, field->data_size, fixedSize); + // support for fixed size is not possible with a single item + bool fixedSize = false; + switch (field->type) { + case B_RECT_TYPE: + case B_POINT_TYPE: + case B_INT8_TYPE: + case B_INT16_TYPE: + case B_INT32_TYPE: + case B_INT64_TYPE: + case B_BOOL_TYPE: + case B_FLOAT_TYPE: + case B_DOUBLE_TYPE: + case B_POINTER_TYPE: + case B_MESSENGER_TYPE: + fixedSize = true; + break; + default: + break; + } - if (status < B_OK) { - free(fieldBuffer); - throw status; - } + status_t result = message.AddData(field->name, field->type, + fieldBuffer + dataOffset, field->itemSize, fixedSize); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + } break; + + case SECTION_FIXED_SIZE_ARRAY_DATA: { + FixedSizeArray *field = (FixedSizeArray *)fieldBuffer; + + int32 dataOffset = sizeof(FixedSizeArray) + field->nameLength + 1; + dataOffset = pad_to_8(dataOffset); + int32 count = *(int32 *)fieldBuffer + dataOffset; + dataOffset += 8; /* count and padding */ + + if (offset + dataOffset + count * field->sizePerItem > size) + return B_BAD_DATA; + + status_t result = B_OK; + for (int32 i = 0; i < count; i++) { + result = message.AddData(field->name, field->type, + fieldBuffer + dataOffset, field->sizePerItem, true, + count); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + + dataOffset += field->sizePerItem; + } + } break; + + case SECTION_VARIABLE_SIZE_ARRAY_DATA: { + VariableSizeArray *field = (VariableSizeArray *)fieldBuffer; + + int32 dataOffset = sizeof(VariableSizeArray) + field->nameLength + 1; + dataOffset = pad_to_8(dataOffset); + int32 count = *(int32 *)fieldBuffer + dataOffset; + dataOffset += sizeof(int32); + ssize_t totalSize = *(ssize_t *)fieldBuffer + dataOffset; + dataOffset += sizeof(ssize_t); + + int32 *endPoints = (int32 *)fieldBuffer + dataOffset + totalSize; + + status_t result = B_OK; + for (int32 i = 0; i < count; i++) { + int32 itemOffset = (i > 0 ? pad_to_8(endPoints[i - 1]) : 0); + + result = message.AddData(field->name, field->type, + fieldBuffer + dataOffset + itemOffset, + endPoints[i] - itemOffset, false, count); + + if (result < B_OK) { + free(fieldBuffer); + throw result; + } + } + } break; } free(fieldBuffer); - offset += fieldHeader.size; -printf("offset = %ld, size = %ld\n", offset, size); + offset += sectionHeader.size; } + message.PrintToStream(); return B_OK; } - diff --git a/src/kits/app/dano_message.h b/src/kits/app/dano_message.h index 03a5a802be..2d0ed7a321 100644 --- a/src/kits/app/dano_message.h +++ b/src/kits/app/dano_message.h @@ -6,6 +6,6 @@ class BDataIO; namespace BPrivate { status_t unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& message); - size_t dano_message_size(const char* buffer); + ssize_t dano_message_size(const char* buffer); }