Moving towards more flat buffering. Speed is still lower than the original Be implementation, but it's not because of the backend, it's probably the slow BMessage::Header implementation.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13909 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -43,16 +43,17 @@ public:
|
|||||||
status_t Flatten(BDataIO *stream) const;
|
status_t Flatten(BDataIO *stream) const;
|
||||||
status_t Unflatten(BDataIO *stream);
|
status_t Unflatten(BDataIO *stream);
|
||||||
|
|
||||||
status_t AddData(const char *name, BSimpleMallocIO *buffer,
|
status_t AddData(const char *name, type_code type,
|
||||||
type_code type);
|
size_t length, void **buffer,
|
||||||
|
bool fixedSize = false, int32 count = 1);
|
||||||
status_t RemoveData(const char *name, int32 index = 0);
|
status_t RemoveData(const char *name, int32 index = 0);
|
||||||
|
|
||||||
bool HasData(const char *name, type_code t, int32 n) const;
|
bool HasData(const char *name, type_code t, int32 n) const;
|
||||||
status_t FindData(const char *name, type_code type,
|
status_t FindData(const char *name, type_code type,
|
||||||
int32 index, const void **data,
|
int32 index, const void **data,
|
||||||
ssize_t *numBytes) const;
|
ssize_t *numBytes) const;
|
||||||
status_t ReplaceData(const char *name, int32 index,
|
status_t ReplaceData(const char *name, type_code type,
|
||||||
BSimpleMallocIO *buffer, type_code type);
|
int32 index, size_t length, void **buffer);
|
||||||
|
|
||||||
status_t Rename(const char *oldName, const char *newName);
|
status_t Rename(const char *oldName, const char *newName);
|
||||||
status_t RemoveName(const char *name);
|
status_t RemoveName(const char *name);
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
#ifndef _MESSAGE_FIELD_H_
|
#ifndef _MESSAGE_FIELD_H_
|
||||||
#define _MESSAGE_FIELD_H_
|
#define _MESSAGE_FIELD_H_
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <String.h>
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
#define MSG_FLAG_VALID 0x01
|
#define MSG_FLAG_VALID 0x01
|
||||||
@@ -25,36 +25,47 @@
|
|||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
class BSimpleMallocIO;
|
typedef struct field_header_s {
|
||||||
|
uint8 flags;
|
||||||
|
type_code type;
|
||||||
|
int32 count;
|
||||||
|
ssize_t dataSize;
|
||||||
|
uint8 nameLength;
|
||||||
|
char name[255];
|
||||||
|
} __attribute__((__packed__)) FieldHeader;
|
||||||
|
|
||||||
class BMessageField {
|
class BMessageField {
|
||||||
public:
|
public:
|
||||||
BMessageField();
|
BMessageField();
|
||||||
BMessageField(const char *name, type_code type);
|
BMessageField(const char *name, type_code type);
|
||||||
|
BMessageField(uint8 flags, BDataIO *stream);
|
||||||
BMessageField(const BMessageField &other);
|
BMessageField(const BMessageField &other);
|
||||||
~BMessageField();
|
~BMessageField();
|
||||||
|
|
||||||
BMessageField &operator=(const BMessageField &other);
|
BMessageField &operator=(const BMessageField &other);
|
||||||
|
|
||||||
uint8 Flags();
|
void Flatten(BDataIO *stream);
|
||||||
|
void Unflatten(uint8 flags, BDataIO *stream);
|
||||||
|
|
||||||
|
uint8 Flags() { return fHeader.flags; };
|
||||||
|
|
||||||
void SetName(const char *name);
|
void SetName(const char *name);
|
||||||
const char *Name() const { return fName.String(); };
|
const char *Name() const { return fHeader.name; };
|
||||||
uint8 NameLength() const { return fName.Length(); };
|
uint8 NameLength() const { return fHeader.nameLength; };
|
||||||
type_code Type() const { return fType; };
|
type_code Type() const { return fHeader.type; };
|
||||||
|
|
||||||
void AddItem(BSimpleMallocIO *item);
|
void *AddItem(size_t length);
|
||||||
void ReplaceItem(int32 index, BSimpleMallocIO *item);
|
void *ReplaceItem(int32 index, size_t newLength);
|
||||||
void RemoveItem(int32 index);
|
void RemoveItem(int32 index);
|
||||||
int32 CountItems() const { return fItems.CountItems(); };
|
int32 CountItems() const { return fHeader.count; };
|
||||||
size_t SizeAt(int32 index) const;
|
|
||||||
const void *BufferAt(int32 index) const;
|
const void *BufferAt(int32 index, ssize_t *size) const;
|
||||||
|
|
||||||
void MakeEmpty();
|
void MakeEmpty();
|
||||||
|
|
||||||
bool IsFixedSize() const { return fFixedSize; };
|
status_t SetFixedSize(int32 itemSize, int32 count);
|
||||||
size_t TotalSize() const { return fTotalSize; };
|
bool IsFixedSize() const { return fHeader.flags & MSG_FLAG_FIXED_SIZE; };
|
||||||
size_t TotalPadding() const { return fTotalPadding; };
|
size_t TotalSize() const { return fHeader.dataSize; };
|
||||||
|
|
||||||
void PrintToStream() const;
|
void PrintToStream() const;
|
||||||
|
|
||||||
@@ -63,15 +74,20 @@ public:
|
|||||||
BMessageField *Next() const { return fNext; };
|
BMessageField *Next() const { return fNext; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsFixedSize(type_code type);
|
void ResetHeader(const char *name, type_code type);
|
||||||
|
void FlatResize(int32 offset, size_t oldLength,
|
||||||
|
size_t newLength);
|
||||||
|
|
||||||
BString fName;
|
FieldHeader fHeader;
|
||||||
type_code fType;
|
mutable BMallocIO fFlatBuffer;
|
||||||
BList fItems;
|
|
||||||
bool fFixedSize;
|
|
||||||
size_t fTotalSize;
|
|
||||||
size_t fTotalPadding;
|
|
||||||
|
|
||||||
|
// fixed size items
|
||||||
|
int32 fItemSize;
|
||||||
|
|
||||||
|
// variable sized items
|
||||||
|
BList *fOffsets;
|
||||||
|
|
||||||
|
// hash table support
|
||||||
BMessageField *fNext;
|
BMessageField *fNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+69
-62
@@ -39,7 +39,6 @@
|
|||||||
#include "MessageBody2.h"
|
#include "MessageBody2.h"
|
||||||
#include "MessageField2.h"
|
#include "MessageField2.h"
|
||||||
#include "MessageUtils2.h"
|
#include "MessageUtils2.h"
|
||||||
#include "SimpleMallocIO.h"
|
|
||||||
#include "dano_message.h"
|
#include "dano_message.h"
|
||||||
|
|
||||||
// flags for the overall message (the bitfield is 1 byte)
|
// flags for the overall message (the bitfield is 1 byte)
|
||||||
@@ -82,6 +81,22 @@ static status_t convert_message(const KMessage *fromMessage,
|
|||||||
BMessage *toMessage);
|
BMessage *toMessage);
|
||||||
static ssize_t min_hdr_size();
|
static ssize_t min_hdr_size();
|
||||||
|
|
||||||
|
typedef struct message_header_s {
|
||||||
|
int32 checkSum;
|
||||||
|
int32 flattenedSize;
|
||||||
|
uint32 what;
|
||||||
|
uint8 flags;
|
||||||
|
} __attribute__((__packed__)) MessageHeader;
|
||||||
|
|
||||||
|
typedef struct reply_data_s {
|
||||||
|
port_id replyPort;
|
||||||
|
int32 replyToken;
|
||||||
|
team_id replyTeam;
|
||||||
|
bool preferredTarget;
|
||||||
|
bool replyRequired;
|
||||||
|
bool replyDone;
|
||||||
|
bool isReply;
|
||||||
|
} __attribute__((__packed__)) ReplyData;
|
||||||
|
|
||||||
class BMessage::Header {
|
class BMessage::Header {
|
||||||
public:
|
public:
|
||||||
@@ -1028,7 +1043,7 @@ BMessage::PopSpecifier()
|
|||||||
status_t \
|
status_t \
|
||||||
BMessage::Add ## fnName(const char *name, TYPE val) \
|
BMessage::Add ## fnName(const char *name, TYPE val) \
|
||||||
{ \
|
{ \
|
||||||
return AddData(name, TYPESPEC, &val, sizeof(TYPE)); \
|
return AddData(name, TYPESPEC, &val, sizeof(TYPE), true); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
status_t \
|
status_t \
|
||||||
@@ -1122,44 +1137,46 @@ DEFINE_LAZY_FIND_FUNCTION(const char *, String);
|
|||||||
status_t
|
status_t
|
||||||
BMessage::AddString(const char *name, const char *string)
|
BMessage::AddString(const char *name, const char *string)
|
||||||
{
|
{
|
||||||
return AddData(name, B_STRING_TYPE, string, strlen(string) + 1);
|
return AddData(name, B_STRING_TYPE, string, strlen(string) + 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessage::AddString(const char* name, const BString &string)
|
BMessage::AddString(const char* name, const BString &string)
|
||||||
{
|
{
|
||||||
return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1);
|
return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessage::AddPointer(const char *name, const void *pointer)
|
BMessage::AddPointer(const char *name, const void *pointer)
|
||||||
{
|
{
|
||||||
return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer));
|
return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessage::AddMessenger(const char *name, BMessenger messenger)
|
BMessage::AddMessenger(const char *name, BMessenger messenger)
|
||||||
{
|
{
|
||||||
return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger));
|
return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessage::AddRef(const char* name, const entry_ref* ref)
|
BMessage::AddRef(const char *name, const entry_ref *ref)
|
||||||
{
|
{
|
||||||
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
|
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
char flatRef[size];
|
||||||
status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref);
|
status_t error = entry_ref_flatten(flatRef, &size, ref);
|
||||||
buffer->SetSize(size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
|
||||||
error = fBody->AddData(name, buffer, B_REF_TYPE);
|
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
error = fBody->AddData(name, B_REF_TYPE, size, &buffer, false);
|
||||||
|
|
||||||
|
if (error >= B_OK)
|
||||||
|
memcpy(buffer, flatRef, size);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -1169,16 +1186,14 @@ status_t
|
|||||||
BMessage::AddMessage(const char *name, const BMessage *msg)
|
BMessage::AddMessage(const char *name, const BMessage *msg)
|
||||||
{
|
{
|
||||||
size_t size = msg->FlattenedSize();
|
size_t size = msg->FlattenedSize();
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
|
||||||
status_t error = msg->Flatten(buffer->Buffer(), size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
void *buffer;
|
||||||
error = fBody->AddData(name, buffer, B_MESSAGE_TYPE);
|
status_t error = fBody->AddData(name, B_MESSAGE_TYPE, size, &buffer, false);
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
return msg->Flatten((char *)buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1186,36 +1201,29 @@ status_t
|
|||||||
BMessage::AddFlat(const char *name, BFlattenable *object, int32 count)
|
BMessage::AddFlat(const char *name, BFlattenable *object, int32 count)
|
||||||
{
|
{
|
||||||
ssize_t size = object->FlattenedSize();
|
ssize_t size = object->FlattenedSize();
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
|
||||||
status_t error = object->Flatten(buffer->Buffer(), size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
void *buffer;
|
||||||
error = fBody->AddData(name, buffer, object->TypeCode());
|
status_t error = fBody->AddData(name, object->TypeCode(), size, &buffer, false);
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
return object->Flatten(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessage::AddData(const char *name, type_code type, const void *data,
|
BMessage::AddData(const char *name, type_code type, const void *data,
|
||||||
ssize_t numBytes, bool is_fixed_size, int32 /*count*/)
|
ssize_t numBytes, bool is_fixed_size, int32 count)
|
||||||
{
|
{
|
||||||
// TODO: test
|
void *buffer;
|
||||||
// In particular, we want to see what happens if is_fixed_size == true and
|
status_t error = fBody->AddData(name, type, numBytes, &buffer, is_fixed_size, count);
|
||||||
// the user attempts to add something bigger or smaller. We may need to
|
|
||||||
// enforce the size thing.
|
|
||||||
|
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(numBytes);
|
|
||||||
buffer->Write(data);
|
|
||||||
status_t error = fBody->AddData(name, buffer, type);
|
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
memcpy(buffer, data, numBytes);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1490,17 +1498,20 @@ status_t
|
|||||||
BMessage::ReplaceRef(const char *name, int32 index, const entry_ref *ref)
|
BMessage::ReplaceRef(const char *name, int32 index, const entry_ref *ref)
|
||||||
{
|
{
|
||||||
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
|
size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH;
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
char flatRef[size];
|
||||||
status_t error = entry_ref_flatten(buffer->Buffer(), &size, ref);
|
status_t error = entry_ref_flatten(flatRef, &size, ref);
|
||||||
buffer->SetSize(size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
|
||||||
error = fBody->ReplaceData(name, index, buffer, B_REF_TYPE);
|
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
void *buffer;
|
||||||
|
error = fBody->ReplaceData(name, B_REF_TYPE, index, size, &buffer);
|
||||||
|
|
||||||
|
if (error < B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
memcpy(buffer, flatRef, size);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1515,16 +1526,14 @@ status_t
|
|||||||
BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *msg)
|
BMessage::ReplaceMessage(const char *name, int32 index, const BMessage *msg)
|
||||||
{
|
{
|
||||||
size_t size = msg->FlattenedSize();
|
size_t size = msg->FlattenedSize();
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
|
||||||
status_t error = msg->Flatten(buffer->Buffer(), size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
void *buffer;
|
||||||
error = fBody->ReplaceData(name, index, buffer, B_MESSAGE_TYPE);
|
status_t error = fBody->ReplaceData(name, B_MESSAGE_TYPE, index, size, &buffer);
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
return msg->Flatten((char *)buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1539,16 +1548,14 @@ status_t
|
|||||||
BMessage::ReplaceFlat(const char *name, int32 index, BFlattenable *object)
|
BMessage::ReplaceFlat(const char *name, int32 index, BFlattenable *object)
|
||||||
{
|
{
|
||||||
ssize_t size = object->FlattenedSize();
|
ssize_t size = object->FlattenedSize();
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(size);
|
|
||||||
status_t error = object->Flatten(buffer->Buffer(), size);
|
|
||||||
|
|
||||||
if (error >= B_OK)
|
void *buffer;
|
||||||
error = fBody->ReplaceData(name, index, buffer, object->TypeCode());
|
status_t error = fBody->ReplaceData(name, object->TypeCode(), index, size, &buffer);
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
return object->Flatten(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1564,14 +1571,14 @@ status_t
|
|||||||
BMessage::ReplaceData(const char *name, type_code type, int32 index,
|
BMessage::ReplaceData(const char *name, type_code type, int32 index,
|
||||||
const void *data, ssize_t data_size)
|
const void *data, ssize_t data_size)
|
||||||
{
|
{
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(data_size);
|
void *buffer;
|
||||||
buffer->Write(data);
|
status_t error = fBody->ReplaceData(name, type, index, data_size, &buffer);
|
||||||
status_t error = fBody->ReplaceData(name, index, buffer, type);
|
|
||||||
|
|
||||||
if (error < B_OK)
|
if (error < B_OK)
|
||||||
delete buffer;
|
return error;
|
||||||
|
|
||||||
return error;
|
memcpy(buffer, data, data_size);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+22
-164
@@ -9,18 +9,13 @@
|
|||||||
/* BMessageBody handles data storage and retrieval for BMessage. */
|
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
#include "MessageBody2.h"
|
#include "MessageBody2.h"
|
||||||
#include "MessageUtils2.h"
|
#include "MessageUtils2.h"
|
||||||
#include "SimpleMallocIO.h"
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
static int64 sPadding[2] = { 0, 0 };
|
|
||||||
static uint8 sPadLengths[8] = { 4, 3, 2, 1, 0, 7, 6, 5 };
|
|
||||||
|
|
||||||
#define CALC_PADDING_8(x) sPadLengths[x % 8]
|
|
||||||
|
|
||||||
BMessageBody::BMessageBody()
|
BMessageBody::BMessageBody()
|
||||||
{
|
{
|
||||||
InitCommon();
|
InitCommon();
|
||||||
@@ -254,55 +249,8 @@ BMessageBody::FlattenedSize() const
|
|||||||
status_t
|
status_t
|
||||||
BMessageBody::Flatten(BDataIO *stream) const
|
BMessageBody::Flatten(BDataIO *stream) const
|
||||||
{
|
{
|
||||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++)
|
||||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
((BMessageField *)fFieldList.ItemAt(index))->Flatten(stream);
|
||||||
|
|
||||||
uint8 flags = field->Flags();
|
|
||||||
stream->Write(&flags, sizeof(flags));
|
|
||||||
|
|
||||||
type_code type = field->Type();
|
|
||||||
stream->Write(&type, sizeof(type));
|
|
||||||
|
|
||||||
// add item count if not a single item
|
|
||||||
int32 count = field->CountItems();
|
|
||||||
if (!(flags & MSG_FLAG_SINGLE_ITEM)) {
|
|
||||||
if (flags & MSG_FLAG_MINI_DATA) {
|
|
||||||
uint8 miniCount = (uint8)count;
|
|
||||||
stream->Write(&miniCount, sizeof(miniCount));
|
|
||||||
} else
|
|
||||||
stream->Write(&count, sizeof(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
// overall data size (includes padding for non fixed size fields)
|
|
||||||
size_t size = field->TotalSize();
|
|
||||||
if (flags & MSG_FLAG_MINI_DATA) {
|
|
||||||
uint8 miniSize = (uint8)size;
|
|
||||||
stream->Write(&miniSize, sizeof(miniSize));
|
|
||||||
} else
|
|
||||||
stream->Write(&size, sizeof(size));
|
|
||||||
|
|
||||||
// name length
|
|
||||||
uint8 nameLength = field->NameLength();
|
|
||||||
stream->Write(&nameLength, sizeof(nameLength));
|
|
||||||
|
|
||||||
// name
|
|
||||||
stream->Write(field->Name(), nameLength);
|
|
||||||
|
|
||||||
// data items
|
|
||||||
if (flags & MSG_FLAG_FIXED_SIZE) {
|
|
||||||
size = field->SizeAt(0);
|
|
||||||
for (int32 dataIndex = 0; dataIndex < count; dataIndex++)
|
|
||||||
stream->Write(field->BufferAt(dataIndex), size);
|
|
||||||
} else {
|
|
||||||
for (int32 dataIndex = 0; dataIndex < count; dataIndex++) {
|
|
||||||
size = field->SizeAt(dataIndex);
|
|
||||||
stream->Write(&size, sizeof(size));
|
|
||||||
|
|
||||||
stream->Write(field->BufferAt(dataIndex), size);
|
|
||||||
size_t error = stream->Write(sPadding, CALC_PADDING_8(size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 lastEntry = 0;
|
uint8 lastEntry = 0;
|
||||||
size_t error = stream->Write(&lastEntry, sizeof(lastEntry));
|
size_t error = stream->Write(&lastEntry, sizeof(lastEntry));
|
||||||
@@ -322,95 +270,21 @@ BMessageBody::Unflatten(BDataIO *stream)
|
|||||||
if (!IsEmpty())
|
if (!IsEmpty())
|
||||||
MakeEmpty();
|
MakeEmpty();
|
||||||
|
|
||||||
|
BMessageField *newField = NULL;
|
||||||
try {
|
try {
|
||||||
TReadHelper reader(stream);
|
TReadHelper reader(stream);
|
||||||
char name[255];
|
|
||||||
|
|
||||||
uint8 flags;
|
uint8 flags;
|
||||||
reader(flags);
|
reader(flags);
|
||||||
|
|
||||||
while (flags != MSG_LAST_ENTRY) {
|
while (flags != MSG_LAST_ENTRY) {
|
||||||
type_code type;
|
newField = new BMessageField(flags, stream);
|
||||||
reader(type);
|
fFieldList.AddItem(newField);
|
||||||
|
HashInsert(newField);
|
||||||
int32 itemCount;
|
|
||||||
int32 dataLength;
|
|
||||||
uint8 littleData;
|
|
||||||
|
|
||||||
if (flags & MSG_FLAG_SINGLE_ITEM) {
|
|
||||||
itemCount = 1;
|
|
||||||
|
|
||||||
if (flags & MSG_FLAG_MINI_DATA) {
|
|
||||||
reader(littleData);
|
|
||||||
dataLength = littleData;
|
|
||||||
} else
|
|
||||||
reader(dataLength);
|
|
||||||
} else {
|
|
||||||
if (flags & MSG_FLAG_MINI_DATA) {
|
|
||||||
reader(littleData);
|
|
||||||
itemCount = littleData;
|
|
||||||
|
|
||||||
reader(littleData);
|
|
||||||
dataLength = littleData;
|
|
||||||
} else {
|
|
||||||
reader(itemCount);
|
|
||||||
reader(dataLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the name length (1 byte) and name
|
|
||||||
uint8 nameLength;
|
|
||||||
reader(nameLength);
|
|
||||||
reader(name, nameLength);
|
|
||||||
name[nameLength] = '\0';
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// ToDo: Add these swapping capabilities again
|
|
||||||
if (swap) {
|
|
||||||
// Is the data fixed size?
|
|
||||||
if ((flags & MSG_FLAG_FIXED_SIZE) != 0) {
|
|
||||||
// Make sure to swap the data
|
|
||||||
status = swap_data(type, (void*)databuffer, dataLen,
|
|
||||||
B_SWAP_ALWAYS);
|
|
||||||
if (status < B_OK)
|
|
||||||
throw status;
|
|
||||||
} else if (type == B_REF_TYPE) {
|
|
||||||
// Is the data variable size?
|
|
||||||
// Apparently, entry_refs are the only variable-length data
|
|
||||||
// explicitely swapped -- the dev_t and ino_t specifically
|
|
||||||
byte_swap(*(entry_ref*)databuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
status_t error = B_ERROR;
|
|
||||||
BMessageField *field = AddField(name, type, error);
|
|
||||||
if (error < B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (flags & MSG_FLAG_FIXED_SIZE) {
|
|
||||||
int32 itemSize = dataLength / itemCount;
|
|
||||||
|
|
||||||
for (int32 index = 0; index < itemCount; index++) {
|
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(itemSize);
|
|
||||||
reader(buffer->Buffer(), itemSize);
|
|
||||||
field->AddItem(buffer);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char padding[8];
|
|
||||||
ssize_t dataLength;
|
|
||||||
|
|
||||||
for (int32 index = 0; index < itemCount; index++) {
|
|
||||||
reader(dataLength);
|
|
||||||
BSimpleMallocIO *buffer = new BSimpleMallocIO(dataLength);
|
|
||||||
reader(buffer->Buffer(), dataLength);
|
|
||||||
reader(padding, CALC_PADDING_8(dataLength));
|
|
||||||
field->AddItem(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader(flags);
|
reader(flags);
|
||||||
}
|
}
|
||||||
} catch (status_t &error) {
|
} catch (status_t &error) {
|
||||||
|
delete newField;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,34 +293,22 @@ BMessageBody::Unflatten(BDataIO *stream)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessageBody::AddData(const char *name, BSimpleMallocIO *buffer, type_code type)
|
BMessageBody::AddData(const char *name, type_code type, size_t length,
|
||||||
|
void **buffer, bool fixedSize, int32 count)
|
||||||
{
|
{
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
BMessageField *foundField = FindData(name, type, error);
|
BMessageField *newField = AddField(name, type, error);
|
||||||
|
|
||||||
if (error < B_OK) {
|
if (error < B_OK)
|
||||||
if (error == B_NAME_NOT_FOUND) {
|
return error;
|
||||||
// reset the error - we will create the field
|
|
||||||
error = B_OK;
|
if (fixedSize) {
|
||||||
} else {
|
error = newField->SetFixedSize(length, count);
|
||||||
// looking for B_BAD_TYPE here in particular, which would indicate
|
if (error < B_OK)
|
||||||
// that we tried to add data of type X when we already had data of
|
|
||||||
// type Y with the same name
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundField) {
|
|
||||||
// add a new field if it's not yet present
|
|
||||||
BMessageField *newField = new BMessageField(name, type);
|
|
||||||
newField->AddItem(buffer);
|
|
||||||
fFieldList.AddItem(newField);
|
|
||||||
HashInsert(newField);
|
|
||||||
} else {
|
|
||||||
// add to the existing field otherwise
|
|
||||||
foundField->AddItem(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*buffer = newField->AddItem(length);
|
||||||
fFlattenedSize = -1;
|
fFlattenedSize = -1;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -476,8 +338,8 @@ BMessageBody::AddField(const char *name, type_code type, status_t &error)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMessageBody::ReplaceData(const char *name, int32 index, BSimpleMallocIO *buffer,
|
BMessageBody::ReplaceData(const char *name, type_code type, int32 index,
|
||||||
type_code type)
|
size_t length, void **buffer)
|
||||||
{
|
{
|
||||||
if (type == B_ANY_TYPE)
|
if (type == B_ANY_TYPE)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -491,7 +353,7 @@ BMessageBody::ReplaceData(const char *name, int32 index, BSimpleMallocIO *buffer
|
|||||||
if (!field)
|
if (!field)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
field->ReplaceItem(index, buffer);
|
*buffer = field->ReplaceItem(index, length);
|
||||||
fFlattenedSize = -1;
|
fFlattenedSize = -1;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -584,11 +446,7 @@ BMessageBody::FindData(const char *name, type_code type, int32 index,
|
|||||||
if (index >= field->CountItems())
|
if (index >= field->CountItems())
|
||||||
return B_BAD_INDEX;
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
if (data)
|
*data = field->BufferAt(index, numBytes);
|
||||||
*data = field->BufferAt(index);
|
|
||||||
|
|
||||||
if (numBytes)
|
|
||||||
*numBytes = field->SizeAt(index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
+234
-111
@@ -7,35 +7,52 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
#include "MessageField2.h"
|
#include "MessageField2.h"
|
||||||
#include "SimpleMallocIO.h"
|
#include "MessageUtils2.h"
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
#define ROUND_TO_8(x) (fFixedSize ? x : (x + 11) & ~7)
|
inline int32
|
||||||
|
round_to_8(int32 length)
|
||||||
|
{
|
||||||
|
// already includes the + 4 for size_t length field
|
||||||
|
return (length + 11) & ~7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageField::BMessageField()
|
BMessageField::BMessageField()
|
||||||
: fType(0),
|
: fItemSize(0),
|
||||||
fFixedSize(false),
|
fOffsets(NULL),
|
||||||
fTotalSize(0),
|
|
||||||
fNext(NULL)
|
fNext(NULL)
|
||||||
{
|
{
|
||||||
SetName("");
|
ResetHeader("", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageField::BMessageField(const char *name, type_code type)
|
BMessageField::BMessageField(const char *name, type_code type)
|
||||||
: fType(type),
|
: fItemSize(0),
|
||||||
fTotalSize(0),
|
fOffsets(NULL),
|
||||||
fNext(NULL)
|
fNext(NULL)
|
||||||
{
|
{
|
||||||
SetName(name);
|
ResetHeader(name, type);
|
||||||
fFixedSize = IsFixedSize(type);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField::BMessageField(uint8 flags, BDataIO *stream)
|
||||||
|
: fItemSize(0),
|
||||||
|
fOffsets(NULL),
|
||||||
|
fNext(NULL)
|
||||||
|
{
|
||||||
|
Unflatten(flags, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageField::BMessageField(const BMessageField &other)
|
BMessageField::BMessageField(const BMessageField &other)
|
||||||
|
: fItemSize(0),
|
||||||
|
fOffsets(NULL),
|
||||||
|
fNext(NULL)
|
||||||
{
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
@@ -52,18 +69,20 @@ BMessageField::operator=(const BMessageField &other)
|
|||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
MakeEmpty();
|
MakeEmpty();
|
||||||
|
|
||||||
fName = other.fName;
|
|
||||||
fType = other.fType;
|
|
||||||
fFixedSize = other.fFixedSize;
|
|
||||||
fTotalSize = other.fTotalSize;
|
|
||||||
fNext = NULL;
|
fNext = NULL;
|
||||||
|
|
||||||
for (int32 index = 0; index < other.fItems.CountItems(); index++) {
|
memcpy(&fHeader, &other.fHeader, sizeof(FieldHeader));
|
||||||
BSimpleMallocIO *otherBuffer = (BSimpleMallocIO *)other.fItems.ItemAt(index);
|
|
||||||
BSimpleMallocIO *newBuffer = new BSimpleMallocIO(otherBuffer->BufferLength());
|
fFlatBuffer.Write(other.fFlatBuffer.Buffer(), other.fFlatBuffer.BufferLength());
|
||||||
newBuffer->Write(otherBuffer->Buffer());
|
|
||||||
fItems.AddItem((void *)newBuffer);
|
if (other.fOffsets) {
|
||||||
|
int32 count = other.fOffsets->CountItems();
|
||||||
|
fOffsets = new BList(count);
|
||||||
|
|
||||||
|
for (int32 index = 0; index < count; index++)
|
||||||
|
fOffsets->AddItem(other.fOffsets->ItemAt(index));
|
||||||
|
} else {
|
||||||
|
fItemSize = other.fItemSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,97 +91,218 @@ BMessageField::operator=(const BMessageField &other)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMessageField::MakeEmpty()
|
BMessageField::Flatten(BDataIO *stream)
|
||||||
{
|
{
|
||||||
for (int32 index = 0; index < fItems.CountItems(); index++) {
|
// write flat header including name
|
||||||
BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.ItemAt(index);
|
stream->Write(&fHeader, sizeof(fHeader) - sizeof(fHeader.name) + fHeader.nameLength);
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
fItems.MakeEmpty();
|
// write flat data
|
||||||
|
stream->Write(fFlatBuffer.Buffer(), fHeader.dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
void
|
||||||
BMessageField::Flags()
|
BMessageField::Unflatten(uint8 flags, BDataIO *stream)
|
||||||
{
|
{
|
||||||
uint8 flags = MSG_FLAG_VALID;
|
TReadHelper reader(stream);
|
||||||
|
|
||||||
if (fItems.CountItems() == 1)
|
// read the header
|
||||||
flags |= MSG_FLAG_SINGLE_ITEM;
|
if (flags == MSG_FLAG_VALID
|
||||||
|
|| flags == MSG_FLAG_VALID | MSG_FLAG_FIXED_SIZE) {
|
||||||
|
// we can read the header as flat data
|
||||||
|
fHeader.flags = flags;
|
||||||
|
stream->Read(&fHeader.type, sizeof(fHeader) - sizeof(fHeader.flags) - sizeof(fHeader.name));
|
||||||
|
stream->Read(&fHeader.name, fHeader.nameLength);
|
||||||
|
fItemSize = fHeader.dataSize / fHeader.count;
|
||||||
|
} else {
|
||||||
|
// we have to disassemble the header
|
||||||
|
type_code type;
|
||||||
|
reader(type);
|
||||||
|
ResetHeader("", type);
|
||||||
|
|
||||||
if (fTotalSize < 255)
|
if (flags & MSG_FLAG_SINGLE_ITEM) {
|
||||||
flags |= MSG_FLAG_MINI_DATA;
|
fHeader.count = 1;
|
||||||
|
|
||||||
if (fFixedSize)
|
if (flags & MSG_FLAG_MINI_DATA) {
|
||||||
flags |= MSG_FLAG_FIXED_SIZE;
|
uint8 littleData;
|
||||||
|
reader(littleData);
|
||||||
|
fHeader.dataSize = littleData;
|
||||||
|
} else
|
||||||
|
reader(fHeader.dataSize);
|
||||||
|
} else {
|
||||||
|
if (flags & MSG_FLAG_MINI_DATA) {
|
||||||
|
uint8 littleData;
|
||||||
|
reader(littleData);
|
||||||
|
fHeader.count = littleData;
|
||||||
|
|
||||||
return flags;
|
reader(littleData);
|
||||||
|
fHeader.dataSize = littleData;
|
||||||
|
} else {
|
||||||
|
reader(fHeader.count);
|
||||||
|
reader(fHeader.dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader(fHeader.nameLength);
|
||||||
|
reader(fHeader.name, fHeader.nameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now read the data
|
||||||
|
fFlatBuffer.SetSize(fHeader.dataSize);
|
||||||
|
stream->Read((void *)fFlatBuffer.Buffer(), fHeader.dataSize);
|
||||||
|
|
||||||
|
// ToDo: enable swapping
|
||||||
|
// swap the data if necessary
|
||||||
|
if (false) {
|
||||||
|
// is the data fixed size?
|
||||||
|
if (flags & MSG_FLAG_FIXED_SIZE) {
|
||||||
|
// make sure to swap the data
|
||||||
|
status_t status = swap_data(fHeader.type,
|
||||||
|
(void *)fFlatBuffer.Buffer(), fHeader.dataSize, B_SWAP_ALWAYS);
|
||||||
|
if (status < B_OK)
|
||||||
|
throw status;
|
||||||
|
} else if (fHeader.type == B_REF_TYPE) {
|
||||||
|
// apparently, entry_refs are the only variable-length data
|
||||||
|
// explicitely swapped -- the dev_t and ino_t specifically
|
||||||
|
// ToDo: this looks broken
|
||||||
|
byte_swap(*(entry_ref *)fFlatBuffer.Buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::ResetHeader(const char *name, type_code type)
|
||||||
|
{
|
||||||
|
memset(&fHeader, 0, sizeof(fHeader));
|
||||||
|
fHeader.flags |= MSG_FLAG_VALID;
|
||||||
|
fHeader.type = type;
|
||||||
|
SetName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::MakeEmpty()
|
||||||
|
{
|
||||||
|
fFlatBuffer.SetSize(0);
|
||||||
|
|
||||||
|
if (fOffsets)
|
||||||
|
fOffsets->MakeEmpty();
|
||||||
|
|
||||||
|
fHeader.dataSize = 0;
|
||||||
|
fHeader.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageField::SetFixedSize(int32 itemSize, int32 /*count*/)
|
||||||
|
{
|
||||||
|
// ToDo: use count here to preallocate the buffer
|
||||||
|
if (fHeader.count > 0 && itemSize != fItemSize) {
|
||||||
|
debugger("not allowed\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fItemSize = itemSize;
|
||||||
|
fHeader.flags |= MSG_FLAG_FIXED_SIZE;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMessageField::SetName(const char *name)
|
BMessageField::SetName(const char *name)
|
||||||
{
|
{
|
||||||
fName = name;
|
fHeader.nameLength = min_c(strlen(name), 254);
|
||||||
|
memcpy(fHeader.name, name, fHeader.nameLength);
|
||||||
// the name length field is only 1 byte long
|
|
||||||
// ToDo: change this? (BC problem)
|
|
||||||
fName.Truncate(255 - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void *
|
||||||
BMessageField::AddItem(BSimpleMallocIO *item)
|
BMessageField::AddItem(size_t length)
|
||||||
{
|
{
|
||||||
fItems.AddItem((void *)item);
|
fHeader.count++;
|
||||||
fTotalSize += ROUND_TO_8(item->BufferLength());
|
|
||||||
|
int32 offset = fFlatBuffer.BufferLength();
|
||||||
|
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||||
|
fHeader.dataSize += length;
|
||||||
|
fFlatBuffer.SetSize(offset + length);
|
||||||
|
return (char *)fFlatBuffer.Buffer() + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fOffsets)
|
||||||
|
fOffsets = new BList();
|
||||||
|
|
||||||
|
fOffsets->AddItem((void *)offset);
|
||||||
|
|
||||||
|
size_t newLength = round_to_8(length);
|
||||||
|
fHeader.dataSize += newLength;
|
||||||
|
FlatResize(offset, 0, newLength);
|
||||||
|
fFlatBuffer.WriteAt(offset, &length, sizeof(length));
|
||||||
|
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void *
|
||||||
BMessageField::ReplaceItem(int32 index, BSimpleMallocIO *item)
|
BMessageField::ReplaceItem(int32 index, size_t newLength)
|
||||||
{
|
{
|
||||||
BSimpleMallocIO *oldItem = (BSimpleMallocIO *)fItems.ItemAt(index);
|
if (fHeader.flags & MSG_FLAG_FIXED_SIZE)
|
||||||
fItems.ReplaceItem(index, item);
|
return (char *)fFlatBuffer.Buffer() + (index * fItemSize);
|
||||||
|
|
||||||
fTotalSize -= ROUND_TO_8(oldItem->BufferLength());
|
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||||
fTotalSize += ROUND_TO_8(item->BufferLength());
|
|
||||||
|
|
||||||
delete oldItem;
|
size_t oldLength;
|
||||||
|
fFlatBuffer.ReadAt(offset, &oldLength, sizeof(oldLength));
|
||||||
|
fFlatBuffer.WriteAt(offset, &newLength, sizeof(newLength));
|
||||||
|
|
||||||
|
oldLength = round_to_8(oldLength);
|
||||||
|
newLength = round_to_8(newLength);
|
||||||
|
|
||||||
|
if (oldLength == newLength)
|
||||||
|
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||||
|
|
||||||
|
FlatResize(offset, oldLength, newLength);
|
||||||
|
fHeader.dataSize += newLength - oldLength;
|
||||||
|
|
||||||
|
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMessageField::RemoveItem(int32 index)
|
BMessageField::RemoveItem(int32 index)
|
||||||
{
|
{
|
||||||
BSimpleMallocIO *item = (BSimpleMallocIO *)fItems.RemoveItem(index);
|
fHeader.count--;
|
||||||
fTotalSize -= ROUND_TO_8(item->BufferLength());
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||||
|
FlatResize(index * fItemSize, fItemSize, 0);
|
||||||
|
fHeader.dataSize -= fItemSize;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t oldLength;
|
||||||
BMessageField::SizeAt(int32 index) const
|
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||||
{
|
fFlatBuffer.ReadAt(offset, &oldLength, sizeof(oldLength));
|
||||||
BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index);
|
oldLength = round_to_8(oldLength);
|
||||||
|
|
||||||
if (buffer)
|
FlatResize(offset, oldLength, 0);
|
||||||
return buffer->BufferLength();
|
fHeader.dataSize -= oldLength;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const void *
|
const void *
|
||||||
BMessageField::BufferAt(int32 index) const
|
BMessageField::BufferAt(int32 index, ssize_t *size) const
|
||||||
{
|
{
|
||||||
BSimpleMallocIO *buffer = (BSimpleMallocIO *)fItems.ItemAt(index);
|
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||||
|
if (size)
|
||||||
|
*size = fItemSize;
|
||||||
|
|
||||||
if (buffer)
|
return (char *)fFlatBuffer.Buffer() + (index * fItemSize);
|
||||||
return buffer->Buffer();
|
}
|
||||||
|
|
||||||
return NULL;
|
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||||
|
if (size)
|
||||||
|
fFlatBuffer.ReadAt(offset, size, sizeof(ssize_t));
|
||||||
|
|
||||||
|
return (char *)fFlatBuffer.Buffer() + offset + sizeof(ssize_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,53 +313,36 @@ BMessageField::PrintToStream() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
BMessageField::IsFixedSize(type_code type)
|
BMessageField::FlatResize(int32 offset, size_t oldLength, size_t newLength)
|
||||||
{
|
{
|
||||||
switch (type) {
|
ssize_t change = newLength - oldLength;
|
||||||
case B_ANY_TYPE:
|
ssize_t bufferLength = fFlatBuffer.BufferLength();
|
||||||
case B_MESSAGE_TYPE:
|
|
||||||
case B_MIME_TYPE:
|
|
||||||
case B_OBJECT_TYPE:
|
|
||||||
case B_RAW_TYPE:
|
|
||||||
case B_STRING_TYPE:
|
|
||||||
case B_ASCII_TYPE: return false;
|
|
||||||
|
|
||||||
case B_BOOL_TYPE:
|
if (change > 0)
|
||||||
case B_CHAR_TYPE:
|
fFlatBuffer.SetSize(bufferLength + change);
|
||||||
case B_COLOR_8_BIT_TYPE:
|
|
||||||
case B_DOUBLE_TYPE:
|
|
||||||
case B_FLOAT_TYPE:
|
|
||||||
case B_GRAYSCALE_8_BIT_TYPE:
|
|
||||||
case B_INT64_TYPE:
|
|
||||||
case B_INT32_TYPE:
|
|
||||||
case B_INT16_TYPE:
|
|
||||||
case B_INT8_TYPE:
|
|
||||||
case B_MESSENGER_TYPE: // ToDo: test
|
|
||||||
case B_MONOCHROME_1_BIT_TYPE:
|
|
||||||
case B_OFF_T_TYPE:
|
|
||||||
case B_PATTERN_TYPE:
|
|
||||||
case B_POINTER_TYPE:
|
|
||||||
case B_POINT_TYPE:
|
|
||||||
case B_RECT_TYPE:
|
|
||||||
case B_REF_TYPE: // ToDo: test
|
|
||||||
case B_RGB_32_BIT_TYPE:
|
|
||||||
case B_RGB_COLOR_TYPE:
|
|
||||||
case B_SIZE_T_TYPE:
|
|
||||||
case B_SSIZE_T_TYPE:
|
|
||||||
case B_TIME_TYPE:
|
|
||||||
case B_UINT64_TYPE:
|
|
||||||
case B_UINT32_TYPE:
|
|
||||||
case B_UINT16_TYPE:
|
|
||||||
case B_UINT8_TYPE: return true;
|
|
||||||
|
|
||||||
// ToDo: test
|
if (offset == bufferLength) {
|
||||||
case B_MEDIA_PARAMETER_TYPE:
|
// the easy case for adds
|
||||||
case B_MEDIA_PARAMETER_WEB_TYPE:
|
return;
|
||||||
case B_MEDIA_PARAMETER_GROUP_TYPE: return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
ssize_t length = bufferLength - offset - oldLength;
|
||||||
|
if (length > 0) {
|
||||||
|
uint8 *location = (uint8 *)fFlatBuffer.Buffer() + offset;
|
||||||
|
memmove(location + newLength, location + oldLength, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change < 0)
|
||||||
|
fFlatBuffer.SetSize(bufferLength + change);
|
||||||
|
|
||||||
|
for (int32 index = fOffsets->CountItems() - 1; index >= 0; index--) {
|
||||||
|
int32 oldOffset = (int32)fOffsets->ItemAt(index);
|
||||||
|
if (oldOffset <= offset)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fOffsets->ReplaceItem(index, (void *)(offset + change));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
Reference in New Issue
Block a user