/* $Id$ */
/** @file
* OpenHashTable, Haiku Guest Additions.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*
* This code is based on:
*
* VirtualBox Guest Additions for Haiku.
*
* Copyright 2007, Hugo Santos. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_UTIL_OPEN_HASH_TABLE_H
#define _KERNEL_UTIL_OPEN_HASH_TABLE_H
#include <OS.h>
#include <stdlib.h>
#include <string.h>
#ifdef _KERNEL_MODE
# include <KernelExport.h>
# include "kernel_cpp.h"
#endif
/*!
The Definition template must have four methods: `HashKey', `Hash',
`Compare' and `GetLink;. It must also define several types as shown in the
following example:
struct Foo {
int bar;
Foo* fNext;
};
struct HashTableDefinition {
typedef int KeyType;
typedef Foo ValueType;
size_t HashKey(int key) const
{
return key >> 1;
}
size_t Hash(Foo* value) const
{
return HashKey(value->bar);
}
bool Compare(int key, Foo* value) const
{
return value->bar == key;
}
Foo*& GetLink(Foo* value) const
{
return value->fNext;
}
};
*/
struct MallocAllocator
{
{
}
{
}
};
{
// All allocations are of power of 2 lengths.
// regrowth factor: 200 / 256 = 78.125%
// 50 / 256 = 19.53125%
:
fTableSize(0),
fItemCount(0),
{
}
:
fTableSize(0),
fItemCount(0),
{
}
:
fTableSize(0),
fItemCount(0),
{
}
{
}
{
return B_NO_MEMORY;
return B_OK;
}
{
return fTableSize;
}
{
return fItemCount;
}
{
if (fTableSize == 0)
return NULL;
while (slot)
{
break;
}
return slot;
}
{
if (fTableSize == 0)
{
if (!_Resize(kMinimumSize))
return B_NO_MEMORY;
}
return B_OK;
}
{
{
#ifdef _KERNEL_MODE
panic("Hash Table: value already in table.");
#else
debugger("Hash Table: value already in table.");
#endif
}
fItemCount++;
}
// TODO: a ValueType* Remove(const KeyType& key) method is missing
{
if (!RemoveUnchecked(value))
return false;
return true;
}
{
while (slot)
{
{
if (previous)
else
break;
}
}
return false;
{
#ifdef _KERNEL_MODE
panic("Hash Table: duplicate detected.");
#else
debugger("Hash Table: duplicate detected.");
#endif
}
fItemCount--;
return true;
}
/*! Removes all elements from the hash table. No resizing happens. The
elements are not deleted. If \a returnElements is \c true, the method
returns all elements chained via their hash table link.
*/
{
if (this->fItemCount == 0)
return NULL;
if (returnElements)
{
// iterate through all buckets
for (size_t i = 0; i < fTableSize; i++)
{
{
// add the bucket to the list
*nextPointer = element;
// update nextPointer to point to the fNext of the last
// element in the bucket
{
element = *nextPointer;
}
}
}
}
return result;
}
/*! If the table needs resizing, the number of bytes for the required
allocation is returned. If no resizing is needed, 0 is returned.
*/
{
{
// grow table
if (size == 0)
size = kMinimumSize;
size <<= 1;
}
{
// shrink table
size >>= 1;
if (size < kMinimumSize)
size = kMinimumSize;
}
if (size == fTableSize)
return 0;
}
/*! Resizes the table using the given allocation. The allocation must not
be \c NULL. It must be of size \a size, which must a value returned
earlier by ResizeNeeded(). If the size requirements have changed in the
meantime, the method free()s the given allocation and returns \c false,
unless \a force is \c true, in which case the supplied allocation is
used in any event.
Otherwise \c true is returned.
If \a oldTable is non-null and resizing is successful, the old table
will not be freed, but will be returned via this parameter instead.
*/
{
{
return false;
}
return true;
}
{
{
Rewind();
}
{
_GetNext();
return current;
}
void Rewind()
{
// get the first one
fIndex = 0;
_GetNext();
}
Iterator() {}
void _GetNext()
{
if (fNext)
}
};
{
}
{
if (fTableSize == 0)
while (slot)
{
break;
}
}
// for g++ 2.95
{
}
{
return false;
return true;
}
{
if (fTable)
{
for (size_t i = 0; i < fTableSize; i++)
{
while (bucket)
{
}
}
else
}
}
{
}
{
for (size_t i = 0; i < fTableSize; i++)
{
while (bucket) {
return true;
}
}
return false;
}
};
#endif // _KERNEL_UTIL_OPEN_HASH_TABLE_H