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:
Michael Lotz 2005-07-20 21:11:27 +00:00
parent eddf2adc8a
commit bbe759b31b
5 changed files with 191 additions and 39 deletions

View File

@ -59,11 +59,20 @@ public:
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:
BMessageField *FindData(const char *name, type_code type,
status_t &error) const;
BList fFields;
BList fFieldList;
BMessageField **fFieldTable;
int32 fFieldTableSize;
};
} // namespace BPrivate

View File

@ -27,9 +27,13 @@ namespace BPrivate {
class BMessageField {
public:
BMessageField();
BMessageField(const char *name, type_code type);
BMessageField(const BMessageField &other);
~BMessageField();
BMessageField &operator=(const BMessageField &other);
uint8 Flags();
void SetName(const char *name);
@ -45,11 +49,17 @@ public:
size_t SizeAt(int32 index) const;
const void *BufferAt(int32 index) const;
void MakeEmpty();
bool IsFixedSize() const { return fFixedSize; };
size_t TotalSize() const { return fTotalSize; };
void PrintToStream() const;
// hash table support
void SetNext(BMessageField *next) { fNext = next; };
BMessageField *Next() const { return fNext; };
private:
bool IsFixedSize(type_code type);
@ -58,6 +68,8 @@ private:
BList fItems;
bool fFixedSize;
size_t fTotalSize;
BMessageField *fNext;
};
} // namespace BPrivate

View File

@ -438,7 +438,8 @@ void BMessage::_ReservedMessage3() {}
//------------------------------------------------------------------------------
BMessage::BMessage()
: what(0), fBody(NULL)
: what(0),
fBody(NULL)
{
init_data();
}
@ -535,7 +536,7 @@ void BMessage::init_data()
}
else
{
fBody = new BPrivate::BMessageBody;
fBody = new BPrivate::BMessageBody();
}
}
//------------------------------------------------------------------------------
@ -594,7 +595,7 @@ bool BMessage::IsReply() 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();
}
//------------------------------------------------------------------------------

View File

@ -17,11 +17,18 @@ namespace BPrivate {
BMessageBody::BMessageBody()
{
fFieldTableSize = 1;
fFieldTable = new BMessageField *[fFieldTableSize];
HashClear();
}
BMessageBody::BMessageBody(const BMessageBody &other)
{
fFieldTableSize = 1;
fFieldTable = new BMessageField *[fFieldTableSize];
HashClear();
*this = other;
}
@ -29,6 +36,7 @@ BMessageBody::BMessageBody(const BMessageBody &other)
BMessageBody::~BMessageBody()
{
MakeEmpty();
delete fFieldTable;
}
@ -37,10 +45,12 @@ 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);
for (int32 index = 0; index < other.fFieldList.CountItems(); index++) {
BMessageField *otherField = (BMessageField *)other.fFieldList.ItemAt(index);
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
{
int32 index = 0;
int32 fieldCount = fFields.CountItems();
int32 fieldCount = fFieldList.CountItems();
BMessageField *field = NULL;
bool found = false;
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 (index == which) {
@ -140,13 +150,12 @@ BMessageBody::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) c
int32
BMessageBody::CountNames(type_code type) const
{
if (type == B_ANY_TYPE) {
return fFields.CountItems();
}
if (type == B_ANY_TYPE)
return fFieldList.CountItems();
int32 count = 0;
for (int32 index = 0; index < fFields.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
if (field->Type() == type)
count++;
}
@ -158,15 +167,15 @@ BMessageBody::CountNames(type_code type) const
bool
BMessageBody::IsEmpty() const
{
return fFields.CountItems() == 0;
return fFieldList.CountItems() == 0;
}
void
BMessageBody::PrintToStream() const
{
for (int32 index = 0; index < fFields.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
field->PrintToStream();
printf("\n");
}
@ -183,6 +192,7 @@ BMessageBody::Rename(const char *oldName, const char *newName)
return B_NAME_NOT_FOUND;
field->SetName(newName);
HashInsert(HashRemove(oldName));
return B_OK;
}
@ -192,8 +202,8 @@ 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);
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
size += field->TotalSize();
size += field->NameLength();
@ -229,8 +239,8 @@ BMessageBody::Flatten(BDataIO *stream) const
{
status_t error = B_OK;
for (int32 index = 0; index < fFields.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
uint8 flags = field->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
BMessageField *newField = new BMessageField(name, type);
newField->AddItem(buffer);
fFields.AddItem(newField);
fFieldList.AddItem(newField);
HashInsert(newField);
} else {
// add to the existing field otherwise
foundField->AddItem(buffer);
@ -384,7 +395,8 @@ BMessageBody::RemoveName(const char *name)
BMessageField *field = FindData(name, B_ANY_TYPE, error);
if (field) {
fFields.RemoveItem(field);
fFieldList.RemoveItem(field);
HashRemove(name);
delete field;
}
@ -395,12 +407,13 @@ BMessageBody::RemoveName(const char *name)
status_t
BMessageBody::MakeEmpty()
{
for (int32 index = 0; index < fFields.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFields.ItemAt(index);
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
delete field;
}
fFields.MakeEmpty();
fFieldList.MakeEmpty();
HashClear();
return B_OK;
}
@ -455,22 +468,94 @@ BMessageBody::FindData(const char *name, type_code type, status_t &error) const
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;
BMessageField *field = HashLookup(name);
if (field) {
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;
}
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

View File

@ -6,22 +6,67 @@
* Michael Lotz <mmlr@mlotz.ch>
*/
#include <stdio.h>
#include <DataIO.h>
#include <TypeConstants.h>
#include "MessageField2.h"
namespace BPrivate {
BMessageField::BMessageField()
: fType(0),
fTotalSize(0),
fNext(NULL)
{
}
BMessageField::BMessageField(const char *name, type_code type)
: fType(type),
fTotalSize(0)
fTotalSize(0),
fNext(NULL)
{
SetName(name);
fFixedSize = IsFixedSize(type);
}
BMessageField::BMessageField(const BMessageField &other)
{
*this = other;
}
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++) {
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
@ -86,7 +131,7 @@ BMessageField::ReplaceItem(int32 index, BMallocIO *item, bool deleteOld)
void
BMessageField::RemoveItem(int32 index, bool deleteIt)
{
BMallocIO *item = (BMallocIO *)fItems.ItemAt(index);
BMallocIO *item = (BMallocIO *)fItems.RemoveItem(index);
fTotalSize -= item->BufferLength();
if (deleteIt)