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:
+164
-51
@@ -16,35 +16,76 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
struct dano_header {
|
enum {
|
||||||
uint32 code;
|
SECTION_MESSAGE_HEADER = 'FOB2',
|
||||||
int32 size;
|
SECTION_OFFSET_TABLE = 'STof',
|
||||||
uint32 what;
|
SECTION_TARGET_INFORMATION = 'ENwh',
|
||||||
uint32 _unknown;
|
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 {
|
typedef struct section_header_s {
|
||||||
uint32 type;
|
uint32 code;
|
||||||
int32 data_size;
|
ssize_t size;
|
||||||
uint8 name_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];
|
char name[0];
|
||||||
} _PACKED;
|
} _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 kMessageFormatSwapped = '2BOF';
|
||||||
|
|
||||||
static const uint32 kDataField = 'SGDa';
|
|
||||||
|
inline int32
|
||||||
|
pad_to_8(int32 value)
|
||||||
|
{
|
||||||
|
return (value + 7) & ~7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
ssize_t
|
||||||
BPrivate::dano_message_size(const char *buffer)
|
BPrivate::dano_message_size(const char *buffer)
|
||||||
{
|
{
|
||||||
dano_header* header = (dano_header*)buffer;
|
SectionHeader *header = (SectionHeader *)buffer;
|
||||||
|
|
||||||
if (header->code == kMessageFormatSwapped)
|
if (header->code == kMessageFormatSwapped)
|
||||||
return __swap_int32(header->size);
|
return __swap_int32(header->size);
|
||||||
@@ -54,7 +95,8 @@ BPrivate::dano_message_size(const char* buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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);
|
TReadHelper reader(&stream);
|
||||||
message.MakeEmpty();
|
message.MakeEmpty();
|
||||||
@@ -62,61 +104,132 @@ BPrivate::unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& messag
|
|||||||
if (magic == kMessageFormatSwapped)
|
if (magic == kMessageFormatSwapped)
|
||||||
reader.SetSwap(true);
|
reader.SetSwap(true);
|
||||||
|
|
||||||
int32 size;
|
ssize_t size;
|
||||||
reader(size);
|
reader(size);
|
||||||
reader(message.what);
|
|
||||||
|
|
||||||
int32 value;
|
MessageHeader header;
|
||||||
reader(value); // unknown
|
reader(header);
|
||||||
|
message.what = header.what;
|
||||||
|
|
||||||
size -= sizeof(dano_header);
|
size -= sizeof(SectionHeader) + sizeof(MessageHeader);
|
||||||
int32 offset = 0;
|
int32 offset = 0;
|
||||||
|
|
||||||
while (offset < size) {
|
while (offset < size) {
|
||||||
dano_field_header fieldHeader;
|
SectionHeader sectionHeader;
|
||||||
reader(fieldHeader);
|
reader(sectionHeader);
|
||||||
printf("field.code = %.4s (%lx), field.size = %ld\n",
|
|
||||||
(char*)&fieldHeader.code, fieldHeader.code, fieldHeader.size);
|
|
||||||
|
|
||||||
if (fieldHeader.size + offset > size)
|
if (offset + sectionHeader.size > size)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
uint32 fieldSize = fieldHeader.size - sizeof(dano_field_header);
|
ssize_t fieldSize = sectionHeader.size - sizeof(SectionHeader);
|
||||||
char* fieldBuffer = (char*)malloc(fieldSize);
|
uint8 *fieldBuffer = (uint8 *)malloc(fieldSize);
|
||||||
if (fieldBuffer == NULL)
|
if (fieldBuffer == NULL)
|
||||||
throw (status_t)B_NO_MEMORY;
|
throw (status_t)B_NO_MEMORY;
|
||||||
|
|
||||||
reader(fieldBuffer, fieldSize);
|
reader(fieldBuffer, fieldSize);
|
||||||
|
|
||||||
if (fieldHeader.code == kDataField) {
|
switch (sectionHeader.code) {
|
||||||
dano_field* field = (dano_field*)fieldBuffer;
|
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;
|
case SECTION_SINGLE_ITEM_DATA: {
|
||||||
dataOffset = (dataOffset + 7) & ~7;
|
SingleItem *field = (SingleItem *)fieldBuffer;
|
||||||
// padding
|
|
||||||
|
|
||||||
if (field->data_size + dataOffset + offset > size)
|
int32 dataOffset = sizeof(SingleItem) + field->nameLength + 1;
|
||||||
|
dataOffset = pad_to_8(dataOffset);
|
||||||
|
|
||||||
|
if (offset + dataOffset + field->itemSize > size)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
// ToDo: support fixed size for real
|
// support for fixed size is not possible with a single item
|
||||||
bool fixedSize = true;
|
bool fixedSize = false;
|
||||||
if (field->type == B_STRING_TYPE)
|
switch (field->type) {
|
||||||
fixedSize = false;
|
case B_RECT_TYPE:
|
||||||
|
case B_POINT_TYPE:
|
||||||
status_t status = message.AddData(field->name, field->type,
|
case B_INT8_TYPE:
|
||||||
fieldBuffer + dataOffset, field->data_size, fixedSize);
|
case B_INT16_TYPE:
|
||||||
|
case B_INT32_TYPE:
|
||||||
if (status < B_OK) {
|
case B_INT64_TYPE:
|
||||||
free(fieldBuffer);
|
case B_BOOL_TYPE:
|
||||||
throw status;
|
case B_FLOAT_TYPE:
|
||||||
|
case B_DOUBLE_TYPE:
|
||||||
|
case B_POINTER_TYPE:
|
||||||
|
case B_MESSENGER_TYPE:
|
||||||
|
fixedSize = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
free(fieldBuffer);
|
||||||
offset += fieldHeader.size;
|
offset += sectionHeader.size;
|
||||||
printf("offset = %ld, size = %ld\n", offset, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message.PrintToStream();
|
message.PrintToStream();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ class BDataIO;
|
|||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
status_t unflatten_dano_message(uint32 magic, BDataIO& stream, BMessage& message);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user