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
This commit is contained in:
Michael Lotz
2005-11-07 01:39:34 +00:00
parent 4f34cedfba
commit 5f9ebca64c
2 changed files with 168 additions and 55 deletions
+167 -54
View File
@@ -16,35 +16,76 @@
#include <stdlib.h>
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;
}
+1 -1
View File
@@ -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);
}