diff --git a/headers/private/app/MessageBody2.h b/headers/private/app/MessageBody2.h index 181419f7a1..9d660c7128 100644 --- a/headers/private/app/MessageBody2.h +++ b/headers/private/app/MessageBody2.h @@ -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 diff --git a/headers/private/app/MessageField2.h b/headers/private/app/MessageField2.h index 10512b1f4f..e47b633699 100644 --- a/headers/private/app/MessageField2.h +++ b/headers/private/app/MessageField2.h @@ -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 diff --git a/src/kits/app/Message2.cpp b/src/kits/app/Message2.cpp index 1c9e47f4c0..1813c2c8b9 100644 --- a/src/kits/app/Message2.cpp +++ b/src/kits/app/Message2.cpp @@ -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(); } //------------------------------------------------------------------------------ diff --git a/src/kits/app/MessageBody2.cpp b/src/kits/app/MessageBody2.cpp index fce79e56bd..b3d780c7b3 100644 --- a/src/kits/app/MessageBody2.cpp +++ b/src/kits/app/MessageBody2.cpp @@ -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 diff --git a/src/kits/app/MessageField2.cpp b/src/kits/app/MessageField2.cpp index d97148e7d8..161fd5aadc 100644 --- a/src/kits/app/MessageField2.cpp +++ b/src/kits/app/MessageField2.cpp @@ -6,22 +6,67 @@ * Michael Lotz */ +#include #include #include #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)