Added a new BMessageBody and BMessageField implementation and added a version of BMessage to
use it. It is not (yet) included in the build and won't break anything. As we now only have thin wrappers around the *Data() functions, the templatized implementation does not make much sense anymore and wouldn't work either. I started this new implementation to be as clean as possible. Instead of using a std::map and BDataBuffer it uses BList and BMallocIO. It passes the unit tests and it even seems to be a bit quicker in some tests (but not as quick as the R5 one). Flattening/Unflattening does not work yet so you can't use it under Haiku right now. It's completely work in progress (I started it just 4 hours ago). Shout if you see something completely broken, reviews welcome. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13776 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||||
|
|
||||||
|
#ifndef _MESSAGE_BODY_H_
|
||||||
|
#define _MESSAGE_BODY_H_
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
#include "MessageField.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
B_FLATTENABLE_TYPE = 'FLAT'
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
class BMessageBody {
|
||||||
|
public:
|
||||||
|
BMessageBody();
|
||||||
|
BMessageBody(const BMessageBody &other);
|
||||||
|
~BMessageBody();
|
||||||
|
|
||||||
|
BMessageBody &operator=(const BMessageBody &other);
|
||||||
|
|
||||||
|
status_t GetInfo(type_code typeRequested, int32 which,
|
||||||
|
char **name, type_code *typeFound,
|
||||||
|
int32 *countFound = NULL) const;
|
||||||
|
status_t GetInfo(const char *name, type_code *typeFound,
|
||||||
|
int32 *countFound = NULL) const;
|
||||||
|
status_t GetInfo(const char *name, type_code *typeFound,
|
||||||
|
bool *fixedSize) const;
|
||||||
|
|
||||||
|
int32 CountNames(type_code type) const;
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
ssize_t FlattenedSize() const;
|
||||||
|
status_t Flatten(BDataIO *stream) const;
|
||||||
|
|
||||||
|
status_t AddData(const char *name, BMallocIO *buffer,
|
||||||
|
type_code type);
|
||||||
|
status_t RemoveData(const char *name, int32 index = 0);
|
||||||
|
|
||||||
|
bool HasData(const char *name, type_code t, int32 n) const;
|
||||||
|
status_t FindData(const char *name, type_code type,
|
||||||
|
int32 index, const void **data,
|
||||||
|
ssize_t *numBytes) const;
|
||||||
|
status_t ReplaceData(const char *name, int32 index,
|
||||||
|
BMallocIO *buffer, type_code type);
|
||||||
|
|
||||||
|
status_t Rename(const char *oldName, const char *newName);
|
||||||
|
status_t RemoveName(const char *name);
|
||||||
|
status_t MakeEmpty();
|
||||||
|
|
||||||
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessageField *FindData(const char *name, type_code type,
|
||||||
|
status_t &error) const;
|
||||||
|
|
||||||
|
BList fFields;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
#endif // _MESSAGE_BODY_H_
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BMessageField contains the data for indiviual named fields in BMessageBody */
|
||||||
|
|
||||||
|
#ifndef _MESSAGE_FIELD_H_
|
||||||
|
#define _MESSAGE_FIELD_H_
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#define MSG_FLAG_VALID 0x01
|
||||||
|
#define MSG_FLAG_MINI_DATA 0x02
|
||||||
|
#define MSG_FLAG_FIXED_SIZE 0x04
|
||||||
|
#define MSG_FLAG_SINGLE_ITEM 0x08
|
||||||
|
#define MSG_FLAG_ALL 0x0F
|
||||||
|
|
||||||
|
#define MSG_LAST_ENTRY 0x00
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
class BMessageField {
|
||||||
|
public:
|
||||||
|
BMessageField(const char *name, type_code type);
|
||||||
|
~BMessageField();
|
||||||
|
|
||||||
|
uint8 Flags();
|
||||||
|
|
||||||
|
void SetName(const char *name);
|
||||||
|
const char *Name() const { return fName.String(); };
|
||||||
|
uint8 NameLength() const { return fName.Length(); };
|
||||||
|
type_code Type() const { return fType; };
|
||||||
|
|
||||||
|
void AddItem(BMallocIO *item);
|
||||||
|
void ReplaceItem(int32 index, BMallocIO *item,
|
||||||
|
bool deleteOld = true);
|
||||||
|
void RemoveItem(int32 index, bool deleteIt = true);
|
||||||
|
int32 CountItems() const { return fItems.CountItems(); };
|
||||||
|
size_t SizeAt(int32 index) const;
|
||||||
|
const void *BufferAt(int32 index) const;
|
||||||
|
|
||||||
|
bool IsFixedSize() const { return fFixedSize; };
|
||||||
|
size_t TotalSize() const { return fTotalSize; };
|
||||||
|
|
||||||
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsFixedSize(type_code type);
|
||||||
|
|
||||||
|
BString fName;
|
||||||
|
type_code fType;
|
||||||
|
BList fItems;
|
||||||
|
bool fFixedSize;
|
||||||
|
size_t fTotalSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
#endif // _MESSAGE_FIELD_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,477 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <DataIO.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
#include <MessageBody.h>
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
BMessageBody::BMessageBody()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageBody::BMessageBody(const BMessageBody &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageBody::~BMessageBody()
|
||||||
|
{
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageBody &
|
||||||
|
BMessageBody::operator=(const BMessageBody &other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
MakeEmpty();
|
||||||
|
for (int32 index = 0; index < other.fFields.CountItems(); index++) {
|
||||||
|
BMessageField *otherField = (BMessageField *)other.fFields.ItemAt(index);
|
||||||
|
BMessageField *newField = new BMessageField(*otherField);
|
||||||
|
fFields.AddItem((void *)newField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::GetInfo(type_code typeRequested, int32 which, char **name,
|
||||||
|
type_code *typeReturned, int32 *count) const
|
||||||
|
{
|
||||||
|
int32 index = 0;
|
||||||
|
int32 fieldCount = fFields.CountItems();
|
||||||
|
BMessageField *field = NULL;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (int32 fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
|
||||||
|
field = (BMessageField *)fFields.ItemAt(fieldIndex);
|
||||||
|
|
||||||
|
if (typeRequested == B_ANY_TYPE || field->Type() == typeRequested) {
|
||||||
|
if (index == which) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we couldn't find any appropriate data
|
||||||
|
if (!found) {
|
||||||
|
if (count)
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
if (index > 0)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
else
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToDo: BC Break
|
||||||
|
// Change 'name' parameter to const char *
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
*name = const_cast<char *>(field->Name());
|
||||||
|
|
||||||
|
if (typeReturned)
|
||||||
|
*typeReturned = field->Type();
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
*count = field->CountItems();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::GetInfo(const char *name, type_code *typeFound,
|
||||||
|
int32 *countFound) const
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
if (typeFound)
|
||||||
|
*typeFound = field->Type();
|
||||||
|
|
||||||
|
if (countFound)
|
||||||
|
*countFound = field->CountItems();
|
||||||
|
} else {
|
||||||
|
if (countFound)
|
||||||
|
*countFound = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) const
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
if (typeFound)
|
||||||
|
*typeFound = field->Type();
|
||||||
|
|
||||||
|
if (fixedSize)
|
||||||
|
*fixedSize = field->IsFixedSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BMessageBody::CountNames(type_code type) const
|
||||||
|
{
|
||||||
|
if (type == B_ANY_TYPE) {
|
||||||
|
return fFields.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 count = 0;
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
if (field->Type() == type)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMessageBody::IsEmpty() const
|
||||||
|
{
|
||||||
|
return fFields.CountItems() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageBody::PrintToStream() const
|
||||||
|
{
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
field->PrintToStream();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::Rename(const char *oldName, const char *newName)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(oldName, B_ANY_TYPE, error);
|
||||||
|
|
||||||
|
if (!field)
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
field->SetName(newName);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
BMessageBody::FlattenedSize() const
|
||||||
|
{
|
||||||
|
ssize_t size = 1; // for MSG_LAST_ENTRY
|
||||||
|
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
size += field->TotalSize();
|
||||||
|
size += field->NameLength();
|
||||||
|
|
||||||
|
// ToDo: too expensive?
|
||||||
|
uint8 flags = field->Flags();
|
||||||
|
size += sizeof(flags);
|
||||||
|
|
||||||
|
// count information
|
||||||
|
if (!(flags & MSG_FLAG_SINGLE_ITEM)) {
|
||||||
|
if (flags & MSG_FLAG_MINI_DATA)
|
||||||
|
size += sizeof(uint8);
|
||||||
|
else
|
||||||
|
size += sizeof(int32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// total size
|
||||||
|
if (flags & MSG_FLAG_MINI_DATA)
|
||||||
|
size += sizeof(uint8);
|
||||||
|
else
|
||||||
|
size += sizeof(size_t);
|
||||||
|
|
||||||
|
// individual sizes
|
||||||
|
if (!(flags & MSG_FLAG_FIXED_SIZE))
|
||||||
|
size += field->CountItems() * sizeof(size_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::Flatten(BDataIO *stream) const
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFixed = flags & MSG_FLAG_FIXED_SIZE;
|
||||||
|
|
||||||
|
// overall data size
|
||||||
|
size_t size = field->TotalSize();
|
||||||
|
printf("totalsize: %ld\n", size);
|
||||||
|
if (!isFixed) {
|
||||||
|
// add bytes for holding each items size
|
||||||
|
size += count * sizeof(size_t);
|
||||||
|
// ToDo: add padding here
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// if we have a fixed size we initialize size once here
|
||||||
|
if (isFixed)
|
||||||
|
size = field->SizeAt(0);
|
||||||
|
|
||||||
|
// data items
|
||||||
|
for (int32 dataIndex = 0; dataIndex < count; dataIndex++) {
|
||||||
|
if (!isFixed) {
|
||||||
|
// set the size for each item
|
||||||
|
size = field->SizeAt(dataIndex);
|
||||||
|
stream->Write(&size, sizeof(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
error = stream->Write(field->BufferAt(dataIndex), size);
|
||||||
|
// ToDo: add padding here too
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error >= B_OK) {
|
||||||
|
error = stream->Write('\0', 1); // MSG_LAST_ENTRY
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *foundField = FindData(name, type, error);
|
||||||
|
|
||||||
|
if (error < B_OK) {
|
||||||
|
if (error == B_NAME_NOT_FOUND) {
|
||||||
|
// reset the error - we will create the field
|
||||||
|
error = B_OK;
|
||||||
|
} else {
|
||||||
|
// looking for B_BAD_TYPE here in particular, which would indicate
|
||||||
|
// that we tried to add data of type X when we already had data of
|
||||||
|
// type Y with the same name
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundField) {
|
||||||
|
// add a new field if it's not yet present
|
||||||
|
BMessageField *newField = new BMessageField(name, type);
|
||||||
|
newField->AddItem(buffer);
|
||||||
|
fFields.AddItem(newField);
|
||||||
|
} else {
|
||||||
|
// add to the existing field otherwise
|
||||||
|
foundField->AddItem(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::ReplaceData(const char *name, int32 index, BMallocIO *buffer,
|
||||||
|
type_code type)
|
||||||
|
{
|
||||||
|
if (type == B_ANY_TYPE)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(name, type, error);
|
||||||
|
|
||||||
|
if (error < B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (!field)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
field->ReplaceItem(index, buffer);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::RemoveData(const char *name, int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0) {
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
if (index < field->CountItems()) {
|
||||||
|
field->RemoveItem(index);
|
||||||
|
|
||||||
|
if (field->CountItems() == 0) {
|
||||||
|
RemoveName(name);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
error = B_BAD_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::RemoveName(const char *name)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
fFields.RemoveItem(field);
|
||||||
|
delete field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::MakeEmpty()
|
||||||
|
{
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
delete field;
|
||||||
|
}
|
||||||
|
|
||||||
|
fFields.MakeEmpty();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMessageBody::HasData(const char *name, type_code type, int32 n) const
|
||||||
|
{
|
||||||
|
if (!name || n < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
status_t error;
|
||||||
|
BMessageField *field = FindData(name, type, error);
|
||||||
|
|
||||||
|
if (!field)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (n >= field->CountItems())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMessageBody::FindData(const char *name, type_code type, int32 index,
|
||||||
|
const void **data, ssize_t *numBytes) const
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
*data = NULL;
|
||||||
|
|
||||||
|
BMessageField *field = FindData(name, type, error);
|
||||||
|
if (error >= B_OK) {
|
||||||
|
if (index >= field->CountItems())
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
*data = field->BufferAt(index);
|
||||||
|
|
||||||
|
if (numBytes)
|
||||||
|
*numBytes = field->SizeAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField *
|
||||||
|
BMessageBody::FindData(const char *name, type_code type, status_t &error) const
|
||||||
|
{
|
||||||
|
if (!name) {
|
||||||
|
error = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
||||||
|
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
||||||
|
|
||||||
|
if (strcmp(name, field->Name()) == 0) {
|
||||||
|
if (type != B_ANY_TYPE && field->Type() != type) {
|
||||||
|
error = B_BAD_TYPE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = B_OK;
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error = B_NAME_NOT_FOUND;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <mmlr@mlotz.ch>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <DataIO.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
#include "MessageField.h"
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
BMessageField::BMessageField(const char *name, type_code type)
|
||||||
|
: fType(type),
|
||||||
|
fTotalSize(0)
|
||||||
|
{
|
||||||
|
SetName(name);
|
||||||
|
fFixedSize = IsFixedSize(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField::~BMessageField()
|
||||||
|
{
|
||||||
|
for (int32 index = 0; index < fItems.CountItems(); index++) {
|
||||||
|
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
fItems.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
BMessageField::Flags()
|
||||||
|
{
|
||||||
|
uint8 flags = MSG_FLAG_VALID;
|
||||||
|
|
||||||
|
if (fItems.CountItems() == 1)
|
||||||
|
flags |= MSG_FLAG_SINGLE_ITEM;
|
||||||
|
|
||||||
|
if (fTotalSize < 255)
|
||||||
|
flags |= MSG_FLAG_MINI_DATA;
|
||||||
|
|
||||||
|
if (fFixedSize)
|
||||||
|
flags |= MSG_FLAG_FIXED_SIZE;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::SetName(const char *name)
|
||||||
|
{
|
||||||
|
fName = name;
|
||||||
|
|
||||||
|
// the name length field is only 1 byte long
|
||||||
|
// ToDo: change this? (BC problem)
|
||||||
|
fName.Truncate(255 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::AddItem(BMallocIO *item)
|
||||||
|
{
|
||||||
|
fItems.AddItem((void *)item);
|
||||||
|
fTotalSize += item->BufferLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::ReplaceItem(int32 index, BMallocIO *item, bool deleteOld)
|
||||||
|
{
|
||||||
|
BMallocIO *oldItem = (BMallocIO *)fItems.ItemAt(index);
|
||||||
|
fTotalSize -= oldItem->BufferLength();
|
||||||
|
|
||||||
|
fItems.ReplaceItem(index, item);
|
||||||
|
fTotalSize += item->BufferLength();
|
||||||
|
|
||||||
|
if (deleteOld)
|
||||||
|
delete oldItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::RemoveItem(int32 index, bool deleteIt)
|
||||||
|
{
|
||||||
|
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
|
||||||
|
|
||||||
|
fTotalSize -= item->BufferLength();
|
||||||
|
if (deleteIt)
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
BMessageField::SizeAt(int32 index) const
|
||||||
|
{
|
||||||
|
BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index);
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
return buffer->BufferLength();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const void *
|
||||||
|
BMessageField::BufferAt(int32 index) const
|
||||||
|
{
|
||||||
|
BMallocIO *buffer = (BMallocIO *)fItems.ItemAt(index);
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
return buffer->Buffer();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::PrintToStream() const
|
||||||
|
{
|
||||||
|
// ToDo: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMessageField::IsFixedSize(type_code type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case B_ANY_TYPE:
|
||||||
|
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:
|
||||||
|
case B_CHAR_TYPE:
|
||||||
|
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
|
||||||
|
case B_MEDIA_PARAMETER_TYPE:
|
||||||
|
case B_MEDIA_PARAMETER_WEB_TYPE:
|
||||||
|
case B_MEDIA_PARAMETER_GROUP_TYPE: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
Reference in New Issue
Block a user