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
+10 -1
View File
@@ -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
+12
View File
@@ -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
+4 -3
View File
@@ -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();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
+118 -33
View File
@@ -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,22 +468,94 @@ 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 (type != B_ANY_TYPE && field->Type() != type) {
if (strcmp(name, field->Name()) == 0) { error = B_BAD_TYPE;
if (type != B_ANY_TYPE && field->Type() != type) { return NULL;
error = B_BAD_TYPE;
return NULL;
}
error = B_OK;
return field;
} }
error = B_OK;
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
+47 -2
View File
@@ -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)