Imported MDR. Some code still not entirely functional -- I haven't been able to figure out how to detect SSL, so IMAP and POP have it turned off. PPP auto-detect is also not functional at the moment. Other than that, it seems to work beautifully. Packaging will come later.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
/* BStringList - a string list implementation
|
||||
**
|
||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <List.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
class _EXPORT BStringList;
|
||||
|
||||
#include "StringList.h"
|
||||
|
||||
static uint8 string_hash(const char *string);
|
||||
|
||||
static uint8 string_hash(const char *string) {
|
||||
uint8 hash = 0;
|
||||
for (int i = 0; string[i] != 0; i++)
|
||||
hash ^= string[i];
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
struct string_bucket {
|
||||
const char *string;
|
||||
~string_bucket() {
|
||||
if (string != NULL)
|
||||
free ((void *)(string));
|
||||
}
|
||||
|
||||
struct string_bucket *next;
|
||||
};
|
||||
|
||||
BStringList::BStringList()
|
||||
: BFlattenable(), _items(0), _indexed(new BList)
|
||||
{
|
||||
for (int32 i = 0; i < 256; i++)
|
||||
_buckets[i] = NULL;
|
||||
}
|
||||
|
||||
BStringList::BStringList(const BStringList& from)
|
||||
: BFlattenable(), _items(0), _indexed(new BList)
|
||||
{
|
||||
for (int32 i = 0; i < 256; i++)
|
||||
_buckets[i] = NULL;
|
||||
|
||||
AddList(&from);
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator=(const BStringList &from) {
|
||||
MakeEmpty();
|
||||
|
||||
AddList(&from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool BStringList::IsFixedSize() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
type_code BStringList::TypeCode() const {
|
||||
return 'STRL';
|
||||
}
|
||||
|
||||
ssize_t BStringList::FlattenedSize() const {
|
||||
ssize_t size = 0;
|
||||
struct string_bucket *bkt;
|
||||
for (int32 i = 0; i < 256; i++) {
|
||||
bkt = (struct string_bucket *)(_buckets[i]);
|
||||
while (bkt != NULL) {
|
||||
size += (strlen(bkt->string) + 1);
|
||||
bkt = bkt->next;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
status_t BStringList::Flatten(void *buffer, ssize_t size) const {
|
||||
if (size < FlattenedSize())
|
||||
return B_NO_MEMORY;
|
||||
|
||||
for (int32 i = 0; i < CountItems(); i++) {
|
||||
memcpy(buffer, ItemAt(i), strlen(ItemAt(i)) + 1);
|
||||
buffer = (void *)((const char *)(buffer) + (strlen(ItemAt(i)) + 1));
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
bool BStringList::AllowsTypeCode(type_code code) const {
|
||||
return (code == 'STRL');
|
||||
}
|
||||
|
||||
status_t BStringList::Unflatten(type_code c, const void *buf, ssize_t size) {
|
||||
if (c != 'STRL')
|
||||
return B_ERROR;
|
||||
|
||||
const char *string = (const char *)(buf);
|
||||
|
||||
for (off_t offset = 0; offset < size; offset ++) {
|
||||
if (((int8 *)(buf))[offset] == 0) {
|
||||
AddItem(string);
|
||||
string = (const char *)buf + offset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void BStringList::AddItem(const char *item) {
|
||||
struct string_bucket *new_bkt;
|
||||
|
||||
new_bkt = (struct string_bucket *)_buckets[string_hash(item)];
|
||||
if (new_bkt == NULL) {
|
||||
new_bkt = new struct string_bucket;
|
||||
new_bkt->string = strdup(item);
|
||||
_indexed->AddItem((void *)(new_bkt->string));
|
||||
new_bkt->next = NULL;
|
||||
_buckets[string_hash(item)] = new_bkt;
|
||||
|
||||
_items++;
|
||||
return;
|
||||
}
|
||||
|
||||
while (new_bkt->next != NULL) new_bkt = new_bkt->next;
|
||||
|
||||
new_bkt->next = new struct string_bucket;
|
||||
new_bkt = new_bkt->next;
|
||||
new_bkt->string = strdup(item);
|
||||
_indexed->AddItem((void *)(new_bkt->string));
|
||||
|
||||
new_bkt->next = NULL;
|
||||
_items++;
|
||||
}
|
||||
|
||||
void BStringList::AddList(const BStringList *newItems) {
|
||||
for (int32 i = 0; i < newItems->CountItems(); i++)
|
||||
AddItem((const char *)(newItems->ItemAt(i)));
|
||||
|
||||
/*struct string_bucket *bkt, *new_bkt;
|
||||
for (int32 i = 0; i < 256; i++) {
|
||||
bkt = (struct string_bucket *)(newItems->_buckets[i]);
|
||||
while (bkt != NULL) {
|
||||
new_bkt = (struct string_bucket *)_buckets[i];
|
||||
if (new_bkt == NULL) {
|
||||
new_bkt = new struct string_bucket;
|
||||
new_bkt->string = strdup(bkt->string);
|
||||
_indexed->Add
|
||||
new_bkt->next = NULL;
|
||||
_buckets[i] = new_bkt;
|
||||
_items++;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (new_bkt->next != NULL) new_bkt = new_bkt->next;
|
||||
|
||||
new_bkt->next = new struct string_bucket;
|
||||
new_bkt = new_bkt->next;
|
||||
new_bkt->string = strdup(bkt->string);
|
||||
new_bkt->next = NULL;
|
||||
_items++;
|
||||
|
||||
bkt = bkt->next;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
bool BStringList::RemoveItem(const char *item) {
|
||||
struct string_bucket *bkt = (struct string_bucket *)_buckets[string_hash(item)];
|
||||
|
||||
if (bkt == NULL)
|
||||
return false;
|
||||
|
||||
if (strcmp(bkt->string,item) == 0) {
|
||||
_indexed->RemoveItem(IndexOf(item));
|
||||
_buckets[string_hash(item)] = bkt->next;
|
||||
delete bkt;
|
||||
_items--;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct string_bucket *tmp_bkt;
|
||||
|
||||
while (bkt->next != NULL) {
|
||||
if (strcmp(bkt->next->string,item) == 0) {
|
||||
_indexed->RemoveItem(IndexOf(item));
|
||||
|
||||
tmp_bkt = bkt->next;
|
||||
bkt->next = bkt->next->next;
|
||||
delete tmp_bkt;
|
||||
_items--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bkt = bkt->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BStringList::MakeEmpty() {
|
||||
struct string_bucket *bkt, *next_bkt;
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
bkt = (struct string_bucket *)_buckets[i];
|
||||
_buckets[i] = NULL;
|
||||
|
||||
while (bkt != NULL) {
|
||||
next_bkt = bkt->next;
|
||||
delete bkt;
|
||||
|
||||
bkt = next_bkt;
|
||||
}
|
||||
}
|
||||
|
||||
_indexed->MakeEmpty();
|
||||
|
||||
_items = 0;
|
||||
}
|
||||
|
||||
const char *BStringList::ItemAt(int32 index) const {
|
||||
return (const char *)(_indexed->ItemAt(index));
|
||||
}
|
||||
|
||||
int32 BStringList::IndexOf(const char *item) const {
|
||||
for (int32 i = 0; i < _indexed->CountItems(); i++) {
|
||||
if (strcmp(item,(const char *)_indexed->ItemAt(i)) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BStringList::HasItem(const char *item) const {
|
||||
struct string_bucket *bkt = (struct string_bucket *)_buckets[string_hash(item)];
|
||||
|
||||
while (bkt != NULL) {
|
||||
if (strcmp(bkt->string,item) == 0)
|
||||
return true;
|
||||
|
||||
bkt = bkt->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 BStringList::CountItems() const {
|
||||
return _items;
|
||||
}
|
||||
|
||||
bool BStringList::IsEmpty() const {
|
||||
return (_items == 0);
|
||||
}
|
||||
|
||||
void BStringList::NotHere(BStringList &other_list, BStringList *results) {
|
||||
#if DEBUG
|
||||
assert(_items == _indexed->CountItems());
|
||||
assert(other_list._items == other_list._indexed->CountItems());
|
||||
#endif
|
||||
|
||||
for (int32 i = 0; i < other_list.CountItems(); i++) {
|
||||
if (!HasItem(other_list[i]))
|
||||
results->AddItem(other_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void BStringList::NotThere(BStringList &other_list, BStringList *results) {
|
||||
other_list.NotHere(*this,results);
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator += (const char *item) {
|
||||
AddItem(item);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator += (BStringList &list) {
|
||||
AddList(&list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator -= (const char *item) {
|
||||
RemoveItem(item);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator -= (BStringList &list) {
|
||||
for (int32 i = 0; i < list.CountItems(); i++)
|
||||
RemoveItem(list[i]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BStringList BStringList::operator | (BStringList &list2) {
|
||||
BStringList list(*this);
|
||||
for (int32 i = 0; i < list2.CountItems(); i++) {
|
||||
if (!list.HasItem(list2.ItemAt(i)))
|
||||
list += list2.ItemAt(i);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator |= (BStringList &list2) {
|
||||
for (int32 i = 0; i < list2.CountItems(); i++) {
|
||||
if (!HasItem(list2.ItemAt(i)))
|
||||
AddItem(list2.ItemAt(i));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BStringList BStringList::operator ^ (BStringList &list2) {
|
||||
BStringList list;
|
||||
for (int32 i = 0; i < CountItems(); i++) {
|
||||
if (!list2.HasItem(ItemAt(i)))
|
||||
list += ItemAt(i);
|
||||
}
|
||||
for (int32 i = 0; i < list2.CountItems(); i++) {
|
||||
if (!HasItem(list2.ItemAt(i)))
|
||||
list += list2.ItemAt(i);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
BStringList &BStringList::operator ^= (BStringList &list) {
|
||||
return (*this = *this ^ list);
|
||||
}
|
||||
|
||||
bool BStringList::operator == (BStringList &list) {
|
||||
if (list.CountItems() != CountItems())
|
||||
return false;
|
||||
|
||||
for (int32 i = 0; i < CountItems(); i++) {
|
||||
if (strcmp(list.ItemAt(i),ItemAt(i)) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *BStringList::operator [] (int32 index) {
|
||||
return ItemAt(index);
|
||||
}
|
||||
|
||||
BStringList::~BStringList() {
|
||||
MakeEmpty();
|
||||
|
||||
delete _indexed;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user