Took Ingos considerations into account and added a simple hashtable implementation.
It's currently really broken so don't even try to test it, but you can still review it ;-). Message2.cpp is not yet cleaned - more to come... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13784 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -59,11 +59,20 @@ public:
|
|||||||
|
|
||||||
void PrintToStream() const;
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
// hash table support
|
||||||
|
void HashInsert(BMessageField *field);
|
||||||
|
BMessageField *HashLookup(const char *name) const;
|
||||||
|
BMessageField *HashRemove(const char *name);
|
||||||
|
uint32 HashString(const char *string) const;
|
||||||
|
void HashClear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMessageField *FindData(const char *name, type_code type,
|
BMessageField *FindData(const char *name, type_code type,
|
||||||
status_t &error) const;
|
status_t &error) const;
|
||||||
|
|
||||||
BList fFields;
|
BList fFieldList;
|
||||||
|
BMessageField **fFieldTable;
|
||||||
|
int32 fFieldTableSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -27,9 +27,13 @@ namespace BPrivate {
|
|||||||
|
|
||||||
class BMessageField {
|
class BMessageField {
|
||||||
public:
|
public:
|
||||||
|
BMessageField();
|
||||||
BMessageField(const char *name, type_code type);
|
BMessageField(const char *name, type_code type);
|
||||||
|
BMessageField(const BMessageField &other);
|
||||||
~BMessageField();
|
~BMessageField();
|
||||||
|
|
||||||
|
BMessageField &operator=(const BMessageField &other);
|
||||||
|
|
||||||
uint8 Flags();
|
uint8 Flags();
|
||||||
|
|
||||||
void SetName(const char *name);
|
void SetName(const char *name);
|
||||||
@@ -45,11 +49,17 @@ public:
|
|||||||
size_t SizeAt(int32 index) const;
|
size_t SizeAt(int32 index) const;
|
||||||
const void *BufferAt(int32 index) const;
|
const void *BufferAt(int32 index) const;
|
||||||
|
|
||||||
|
void MakeEmpty();
|
||||||
|
|
||||||
bool IsFixedSize() const { return fFixedSize; };
|
bool IsFixedSize() const { return fFixedSize; };
|
||||||
size_t TotalSize() const { return fTotalSize; };
|
size_t TotalSize() const { return fTotalSize; };
|
||||||
|
|
||||||
void PrintToStream() const;
|
void PrintToStream() const;
|
||||||
|
|
||||||
|
// hash table support
|
||||||
|
void SetNext(BMessageField *next) { fNext = next; };
|
||||||
|
BMessageField *Next() const { return fNext; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsFixedSize(type_code type);
|
bool IsFixedSize(type_code type);
|
||||||
|
|
||||||
@@ -58,6 +68,8 @@ private:
|
|||||||
BList fItems;
|
BList fItems;
|
||||||
bool fFixedSize;
|
bool fFixedSize;
|
||||||
size_t fTotalSize;
|
size_t fTotalSize;
|
||||||
|
|
||||||
|
BMessageField *fNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -438,7 +438,8 @@ void BMessage::_ReservedMessage3() {}
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
BMessage::BMessage()
|
BMessage::BMessage()
|
||||||
: what(0), fBody(NULL)
|
: what(0),
|
||||||
|
fBody(NULL)
|
||||||
{
|
{
|
||||||
init_data();
|
init_data();
|
||||||
}
|
}
|
||||||
@@ -535,7 +536,7 @@ void BMessage::init_data()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fBody = new BPrivate::BMessageBody;
|
fBody = new BPrivate::BMessageBody();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -594,7 +595,7 @@ bool BMessage::IsReply() const
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void BMessage::PrintToStream() const
|
void BMessage::PrintToStream() const
|
||||||
{
|
{
|
||||||
printf("\nBMessage: what = (0x%lX or %ld)\n", what, what);
|
printf("\nBMessage: what = '%c%c%c%c' (0x%lX or %ld)\n", (what >> 24 & 0xff), (what >> 16 & 0xff), (what >> 8 & 0xff), (what & 0xff), what, what);
|
||||||
fBody->PrintToStream();
|
fBody->PrintToStream();
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
+112
-27
@@ -17,11 +17,18 @@ namespace BPrivate {
|
|||||||
|
|
||||||
BMessageBody::BMessageBody()
|
BMessageBody::BMessageBody()
|
||||||
{
|
{
|
||||||
|
fFieldTableSize = 1;
|
||||||
|
fFieldTable = new BMessageField *[fFieldTableSize];
|
||||||
|
HashClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageBody::BMessageBody(const BMessageBody &other)
|
BMessageBody::BMessageBody(const BMessageBody &other)
|
||||||
{
|
{
|
||||||
|
fFieldTableSize = 1;
|
||||||
|
fFieldTable = new BMessageField *[fFieldTableSize];
|
||||||
|
HashClear();
|
||||||
|
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +36,7 @@ BMessageBody::BMessageBody(const BMessageBody &other)
|
|||||||
BMessageBody::~BMessageBody()
|
BMessageBody::~BMessageBody()
|
||||||
{
|
{
|
||||||
MakeEmpty();
|
MakeEmpty();
|
||||||
|
delete fFieldTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -37,10 +45,12 @@ BMessageBody::operator=(const BMessageBody &other)
|
|||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
MakeEmpty();
|
MakeEmpty();
|
||||||
for (int32 index = 0; index < other.fFields.CountItems(); index++) {
|
|
||||||
BMessageField *otherField = (BMessageField *)other.fFields.ItemAt(index);
|
for (int32 index = 0; index < other.fFieldList.CountItems(); index++) {
|
||||||
|
BMessageField *otherField = (BMessageField *)other.fFieldList.ItemAt(index);
|
||||||
BMessageField *newField = new BMessageField(*otherField);
|
BMessageField *newField = new BMessageField(*otherField);
|
||||||
fFields.AddItem((void *)newField);
|
fFieldList.AddItem((void *)newField);
|
||||||
|
HashInsert(newField);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,12 +63,12 @@ BMessageBody::GetInfo(type_code typeRequested, int32 which, char **name,
|
|||||||
type_code *typeReturned, int32 *count) const
|
type_code *typeReturned, int32 *count) const
|
||||||
{
|
{
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
int32 fieldCount = fFields.CountItems();
|
int32 fieldCount = fFieldList.CountItems();
|
||||||
BMessageField *field = NULL;
|
BMessageField *field = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
for (int32 fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
|
for (int32 fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
|
||||||
field = (BMessageField *)fFields.ItemAt(fieldIndex);
|
field = (BMessageField *)fFieldList.ItemAt(fieldIndex);
|
||||||
|
|
||||||
if (typeRequested == B_ANY_TYPE || field->Type() == typeRequested) {
|
if (typeRequested == B_ANY_TYPE || field->Type() == typeRequested) {
|
||||||
if (index == which) {
|
if (index == which) {
|
||||||
@@ -140,13 +150,12 @@ BMessageBody::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) c
|
|||||||
int32
|
int32
|
||||||
BMessageBody::CountNames(type_code type) const
|
BMessageBody::CountNames(type_code type) const
|
||||||
{
|
{
|
||||||
if (type == B_ANY_TYPE) {
|
if (type == B_ANY_TYPE)
|
||||||
return fFields.CountItems();
|
return fFieldList.CountItems();
|
||||||
}
|
|
||||||
|
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||||
if (field->Type() == type)
|
if (field->Type() == type)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -158,15 +167,15 @@ BMessageBody::CountNames(type_code type) const
|
|||||||
bool
|
bool
|
||||||
BMessageBody::IsEmpty() const
|
BMessageBody::IsEmpty() const
|
||||||
{
|
{
|
||||||
return fFields.CountItems() == 0;
|
return fFieldList.CountItems() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMessageBody::PrintToStream() const
|
BMessageBody::PrintToStream() const
|
||||||
{
|
{
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||||
field->PrintToStream();
|
field->PrintToStream();
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -183,6 +192,7 @@ BMessageBody::Rename(const char *oldName, const char *newName)
|
|||||||
return B_NAME_NOT_FOUND;
|
return B_NAME_NOT_FOUND;
|
||||||
|
|
||||||
field->SetName(newName);
|
field->SetName(newName);
|
||||||
|
HashInsert(HashRemove(oldName));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,8 +202,8 @@ BMessageBody::FlattenedSize() const
|
|||||||
{
|
{
|
||||||
ssize_t size = 1; // for MSG_LAST_ENTRY
|
ssize_t size = 1; // for MSG_LAST_ENTRY
|
||||||
|
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||||
size += field->TotalSize();
|
size += field->TotalSize();
|
||||||
size += field->NameLength();
|
size += field->NameLength();
|
||||||
|
|
||||||
@@ -229,8 +239,8 @@ BMessageBody::Flatten(BDataIO *stream) const
|
|||||||
{
|
{
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
|
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||||
|
|
||||||
uint8 flags = field->Flags();
|
uint8 flags = field->Flags();
|
||||||
stream->Write(&flags, sizeof(flags));
|
stream->Write(&flags, sizeof(flags));
|
||||||
@@ -321,7 +331,8 @@ BMessageBody::AddData(const char *name, BMallocIO *buffer, type_code type)
|
|||||||
// add a new field if it's not yet present
|
// add a new field if it's not yet present
|
||||||
BMessageField *newField = new BMessageField(name, type);
|
BMessageField *newField = new BMessageField(name, type);
|
||||||
newField->AddItem(buffer);
|
newField->AddItem(buffer);
|
||||||
fFields.AddItem(newField);
|
fFieldList.AddItem(newField);
|
||||||
|
HashInsert(newField);
|
||||||
} else {
|
} else {
|
||||||
// add to the existing field otherwise
|
// add to the existing field otherwise
|
||||||
foundField->AddItem(buffer);
|
foundField->AddItem(buffer);
|
||||||
@@ -384,7 +395,8 @@ BMessageBody::RemoveName(const char *name)
|
|||||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||||
|
|
||||||
if (field) {
|
if (field) {
|
||||||
fFields.RemoveItem(field);
|
fFieldList.RemoveItem(field);
|
||||||
|
HashRemove(name);
|
||||||
delete field;
|
delete field;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,12 +407,13 @@ BMessageBody::RemoveName(const char *name)
|
|||||||
status_t
|
status_t
|
||||||
BMessageBody::MakeEmpty()
|
BMessageBody::MakeEmpty()
|
||||||
{
|
{
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||||
delete field;
|
delete field;
|
||||||
}
|
}
|
||||||
|
|
||||||
fFields.MakeEmpty();
|
fFieldList.MakeEmpty();
|
||||||
|
HashClear();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,10 +468,8 @@ BMessageBody::FindData(const char *name, type_code type, status_t &error) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 index = 0; index < fFields.CountItems(); index++) {
|
BMessageField *field = HashLookup(name);
|
||||||
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
|
if (field) {
|
||||||
|
|
||||||
if (strcmp(name, field->Name()) == 0) {
|
|
||||||
if (type != B_ANY_TYPE && field->Type() != type) {
|
if (type != B_ANY_TYPE && field->Type() != type) {
|
||||||
error = B_BAD_TYPE;
|
error = B_BAD_TYPE;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -467,10 +478,84 @@ BMessageBody::FindData(const char *name, type_code type, status_t &error) const
|
|||||||
error = B_OK;
|
error = B_OK;
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
error = B_NAME_NOT_FOUND;
|
error = B_NAME_NOT_FOUND;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageBody::HashInsert(BMessageField *field)
|
||||||
|
{
|
||||||
|
uint32 index = HashString(field->Name()) % fFieldTableSize;
|
||||||
|
field->SetNext(fFieldTable[index]);
|
||||||
|
fFieldTable[index] = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField *
|
||||||
|
BMessageBody::HashLookup(const char *name) const
|
||||||
|
{
|
||||||
|
uint32 index = HashString(name) % fFieldTableSize;
|
||||||
|
BMessageField *result = fFieldTable[index];
|
||||||
|
|
||||||
|
while (result) {
|
||||||
|
if (strcmp(result->Name(), name) == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = result->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField *
|
||||||
|
BMessageBody::HashRemove(const char *name)
|
||||||
|
{
|
||||||
|
uint32 index = HashString(name) % fFieldTableSize;
|
||||||
|
BMessageField *result = fFieldTable[index];
|
||||||
|
BMessageField *last = NULL;
|
||||||
|
|
||||||
|
while (result) {
|
||||||
|
if (strcmp(result->Name(), name) == 0) {
|
||||||
|
if (last)
|
||||||
|
last->SetNext(result->Next());
|
||||||
|
else
|
||||||
|
fFieldTable[index] = result->Next();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = result;
|
||||||
|
result = result->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageBody::HashClear()
|
||||||
|
{
|
||||||
|
if (fFieldTable)
|
||||||
|
memset(fFieldTable, 0, fFieldTableSize * sizeof(BMessageField *));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
BMessageBody::HashString(const char *string) const
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
uint32 result = 0;
|
||||||
|
|
||||||
|
while ((ch = *string++) != 0) {
|
||||||
|
result = (result << 7) ^ (result >> 24);
|
||||||
|
result ^= ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
result ^= result << 12;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -6,22 +6,67 @@
|
|||||||
* Michael Lotz <[email protected]>
|
* Michael Lotz <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
#include "MessageField2.h"
|
#include "MessageField2.h"
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
|
BMessageField::BMessageField()
|
||||||
|
: fType(0),
|
||||||
|
fTotalSize(0),
|
||||||
|
fNext(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageField::BMessageField(const char *name, type_code type)
|
BMessageField::BMessageField(const char *name, type_code type)
|
||||||
: fType(type),
|
: fType(type),
|
||||||
fTotalSize(0)
|
fTotalSize(0),
|
||||||
|
fNext(NULL)
|
||||||
{
|
{
|
||||||
SetName(name);
|
SetName(name);
|
||||||
fFixedSize = IsFixedSize(type);
|
fFixedSize = IsFixedSize(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField::BMessageField(const BMessageField &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessageField::~BMessageField()
|
BMessageField::~BMessageField()
|
||||||
|
{
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessageField &
|
||||||
|
BMessageField::operator=(const BMessageField &other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
MakeEmpty();
|
||||||
|
|
||||||
|
fType = other.fType;
|
||||||
|
fName = other.fName;
|
||||||
|
fNext = NULL;
|
||||||
|
|
||||||
|
for (int32 index = 0; index < other.fItems.CountItems(); index++) {
|
||||||
|
BMallocIO *otherBuffer = (BMallocIO *)other.fItems.ItemAt(index);
|
||||||
|
BMallocIO *newBuffer = new BMallocIO;
|
||||||
|
newBuffer->Write(otherBuffer->Buffer(), otherBuffer->BufferLength());
|
||||||
|
fItems.AddItem((void *)newBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMessageField::MakeEmpty()
|
||||||
{
|
{
|
||||||
for (int32 index = 0; index < fItems.CountItems(); index++) {
|
for (int32 index = 0; index < fItems.CountItems(); index++) {
|
||||||
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
|
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
|
||||||
@@ -86,7 +131,7 @@ BMessageField::ReplaceItem(int32 index, BMallocIO *item, bool deleteOld)
|
|||||||
void
|
void
|
||||||
BMessageField::RemoveItem(int32 index, bool deleteIt)
|
BMessageField::RemoveItem(int32 index, bool deleteIt)
|
||||||
{
|
{
|
||||||
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
|
BMallocIO *item = (BMallocIO *)fItems.RemoveItem(index);
|
||||||
|
|
||||||
fTotalSize -= item->BufferLength();
|
fTotalSize -= item->BufferLength();
|
||||||
if (deleteIt)
|
if (deleteIt)
|
||||||
|
|||||||
Reference in New Issue
Block a user