mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 12:42:34 +01:00
Added HandleHashMap.
This commit is contained in:
@@ -8,9 +8,11 @@
|
||||
|
||||
#include "bx.h"
|
||||
#include "allocator.h"
|
||||
#include "uint32_t.h"
|
||||
|
||||
namespace bx
|
||||
{
|
||||
///
|
||||
class HandleAlloc
|
||||
{
|
||||
public:
|
||||
@@ -127,6 +129,7 @@ namespace bx
|
||||
BX_FREE(_allocator, _handleAlloc);
|
||||
}
|
||||
|
||||
///
|
||||
template <uint16_t MaxHandlesT>
|
||||
class HandleAllocT : public HandleAlloc
|
||||
{
|
||||
@@ -144,6 +147,7 @@ namespace bx
|
||||
uint16_t m_padding[2*MaxHandlesT];
|
||||
};
|
||||
|
||||
///
|
||||
template <uint16_t MaxHandlesT>
|
||||
class HandleListT
|
||||
{
|
||||
@@ -327,6 +331,7 @@ namespace bx
|
||||
Link m_links[MaxHandlesT];
|
||||
};
|
||||
|
||||
///
|
||||
template <uint16_t MaxHandlesT>
|
||||
class HandleAllocLruT
|
||||
{
|
||||
@@ -422,6 +427,293 @@ namespace bx
|
||||
HandleAllocT<MaxHandlesT> m_alloc;
|
||||
};
|
||||
|
||||
///
|
||||
template <uint32_t MaxCapacityT, typename KeyT = uint32_t>
|
||||
class HandleHashMapT
|
||||
{
|
||||
public:
|
||||
static const uint16_t invalid = UINT16_MAX;
|
||||
|
||||
HandleHashMapT()
|
||||
: m_maxCapacity(MaxCapacityT)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
~HandleHashMapT()
|
||||
{
|
||||
}
|
||||
|
||||
bool insert(KeyT _key, uint16_t _handle)
|
||||
{
|
||||
if (invalid == _handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const KeyT hash = mix(_key);
|
||||
const uint32_t first = hash % MaxCapacityT;
|
||||
uint32_t idx = first;
|
||||
do
|
||||
{
|
||||
if (m_handle[idx] == invalid)
|
||||
{
|
||||
m_key[idx] = _key;
|
||||
m_handle[idx] = _handle;
|
||||
++m_numElements;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_key[idx] == _key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
idx = (idx + 1) % MaxCapacityT;
|
||||
|
||||
} while (idx != first);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeByKey(KeyT _key)
|
||||
{
|
||||
uint32_t idx = findIndex(_key);
|
||||
if (UINT32_MAX != idx)
|
||||
{
|
||||
m_handle[idx] = invalid;
|
||||
--m_numElements;
|
||||
}
|
||||
}
|
||||
|
||||
void removeByHandle(uint16_t _handle)
|
||||
{
|
||||
if (invalid != _handle)
|
||||
{
|
||||
for (uint32_t idx = 0; idx < MaxCapacityT; ++idx)
|
||||
{
|
||||
if (m_handle[idx] == _handle)
|
||||
{
|
||||
m_handle[idx] = invalid;
|
||||
--m_numElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t find(KeyT _key) const
|
||||
{
|
||||
uint32_t idx = findIndex(_key);
|
||||
if (UINT32_MAX != idx)
|
||||
{
|
||||
return m_handle[idx];
|
||||
}
|
||||
|
||||
return invalid;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
memset(m_handle, 0xff, sizeof(m_handle) );
|
||||
m_numElements = 0;
|
||||
}
|
||||
|
||||
uint32_t getNumElements() const
|
||||
{
|
||||
return m_numElements;
|
||||
}
|
||||
|
||||
uint32_t getMaxCapacity() const
|
||||
{
|
||||
return m_maxCapacity;
|
||||
}
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
uint16_t handle;
|
||||
|
||||
private:
|
||||
friend class HandleHashMapT<MaxCapacityT, KeyT>;
|
||||
uint32_t pos;
|
||||
uint32_t num;
|
||||
};
|
||||
|
||||
Iterator first() const
|
||||
{
|
||||
Iterator it;
|
||||
it.handle = invalid;
|
||||
it.pos = 0;
|
||||
it.num = m_numElements;
|
||||
|
||||
if (0 == it.num)
|
||||
{
|
||||
return it;
|
||||
}
|
||||
|
||||
++it.num;
|
||||
next(it);
|
||||
return it;
|
||||
}
|
||||
|
||||
bool next(Iterator& _it) const
|
||||
{
|
||||
if (0 == _it.num)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (
|
||||
;_it.pos < MaxCapacityT && invalid == m_handle[_it.pos]
|
||||
; ++_it.pos
|
||||
);
|
||||
_it.handle = m_handle[_it.pos];
|
||||
++_it.pos;
|
||||
--_it.num;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t findIndex(KeyT _key) const
|
||||
{
|
||||
const KeyT hash = mix(_key);
|
||||
|
||||
const uint32_t first = hash % MaxCapacityT;
|
||||
uint32_t idx = first;
|
||||
do
|
||||
{
|
||||
if (m_handle[idx] == invalid)
|
||||
{
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
if (m_key[idx] == _key)
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
idx = (idx + 1) % MaxCapacityT;
|
||||
|
||||
} while (idx != first);
|
||||
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
uint32_t mix(uint32_t _x) const
|
||||
{
|
||||
const uint32_t tmp0 = uint32_mul(_x, UINT32_C(2246822519) );
|
||||
const uint32_t tmp1 = uint32_rol(tmp0, 13);
|
||||
const uint32_t result = uint32_mul(tmp1, UINT32_C(2654435761) );
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t mix(uint64_t _x) const
|
||||
{
|
||||
const uint64_t tmp0 = uint64_mul(_x, UINT64_C(14029467366897019727) );
|
||||
const uint64_t tmp1 = uint64_rol(tmp0, 31);
|
||||
const uint64_t result = uint64_mul(tmp1, UINT64_C(11400714785074694791) );
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t m_maxCapacity;
|
||||
uint32_t m_numElements;
|
||||
|
||||
KeyT m_key[MaxCapacityT];
|
||||
uint16_t m_handle[MaxCapacityT];
|
||||
};
|
||||
|
||||
///
|
||||
template <uint16_t MaxHandlesT, typename KeyT = uint32_t>
|
||||
class HandleHashMapAllocT
|
||||
{
|
||||
public:
|
||||
static const uint16_t invalid = UINT16_MAX;
|
||||
|
||||
HandleHashMapAllocT()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
~HandleHashMapAllocT()
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t alloc(KeyT _key)
|
||||
{
|
||||
uint16_t handle = m_alloc.alloc();
|
||||
if (invalid == handle)
|
||||
{
|
||||
return invalid;
|
||||
}
|
||||
|
||||
bool ok = m_table.insert(_key, handle);
|
||||
if (!ok)
|
||||
{
|
||||
m_alloc.free(handle);
|
||||
return invalid;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void free(KeyT _key)
|
||||
{
|
||||
uint16_t handle = m_table.find(_key);
|
||||
if (invalid == handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_table.removeByKey(_key);
|
||||
m_alloc.free(handle);
|
||||
}
|
||||
|
||||
void free(uint16_t _handle)
|
||||
{
|
||||
m_table.removeByHandle(_handle);
|
||||
m_alloc.free(_handle);
|
||||
}
|
||||
|
||||
uint16_t find(KeyT _key) const
|
||||
{
|
||||
return m_table.find(_key);
|
||||
}
|
||||
|
||||
const uint16_t* getHandles() const
|
||||
{
|
||||
return m_alloc.getHandles();
|
||||
}
|
||||
|
||||
uint16_t getHandleAt(uint16_t _at) const
|
||||
{
|
||||
return m_alloc.getHandleAt(_at);
|
||||
}
|
||||
|
||||
uint16_t getNumHandles() const
|
||||
{
|
||||
return m_alloc.getNumHandles();
|
||||
}
|
||||
|
||||
uint16_t getMaxHandles() const
|
||||
{
|
||||
return m_alloc.getMaxHandles();
|
||||
}
|
||||
|
||||
bool isValid(uint16_t _handle) const
|
||||
{
|
||||
return m_alloc.isValid(_handle);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_table.reset();
|
||||
m_alloc.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
HandleHashMapT<MaxHandlesT+MaxHandlesT/2, KeyT> m_table;
|
||||
HandleAllocT<MaxHandlesT> m_alloc;
|
||||
};
|
||||
|
||||
} // namespace bx
|
||||
|
||||
#endif // BX_HANDLE_ALLOC_H_HEADER_GUARD
|
||||
|
||||
@@ -162,6 +162,7 @@ namespace bx
|
||||
template <typename Ty>
|
||||
inline uint32_t hashMurmur2A(const Ty& _data)
|
||||
{
|
||||
BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
|
||||
return hashMurmur2A(&_data, sizeof(Ty) );
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,146 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h> // wchar_t
|
||||
|
||||
#include <bx/allocator.h>
|
||||
#include <bx/hash.h>
|
||||
|
||||
#ifndef va_copy
|
||||
# define va_copy(_a, _b) (_a) = (_b)
|
||||
#endif // va_copy
|
||||
|
||||
namespace bx
|
||||
{
|
||||
/// Non-zero-terminated string view.
|
||||
class StringView
|
||||
{
|
||||
public:
|
||||
StringView()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
StringView(const char* _ptr, uint32_t _len = UINT32_MAX)
|
||||
{
|
||||
clear();
|
||||
|
||||
if (NULL != _ptr)
|
||||
{
|
||||
uint32_t len = UINT32_MAX == _len ? strlen(_ptr) : _len;
|
||||
if (0 != len)
|
||||
{
|
||||
m_len = len;
|
||||
m_ptr = _ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_ptr = "";
|
||||
m_len = 0;
|
||||
}
|
||||
|
||||
const char* getPtr() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
const char* getTerm() const
|
||||
{
|
||||
return m_ptr + m_len;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return 0 == m_len;
|
||||
}
|
||||
|
||||
uint32_t getLength() const
|
||||
{
|
||||
return m_len;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend uint32_t hashMurmur2A(const StringView& _data);
|
||||
|
||||
const char* m_ptr;
|
||||
uint32_t m_len;
|
||||
};
|
||||
|
||||
inline uint32_t hashMurmur2A(const StringView& _data)
|
||||
{
|
||||
return hashMurmur2A(_data.m_ptr, _data.m_len);
|
||||
}
|
||||
|
||||
inline uint32_t hashMurmur2A(const char* _data)
|
||||
{
|
||||
return hashMurmur2A(StringView(_data) );
|
||||
}
|
||||
|
||||
/// ASCII string
|
||||
template<bx::AllocatorI** allocator>
|
||||
class StringT : public StringView
|
||||
{
|
||||
public:
|
||||
StringT()
|
||||
: StringView("", 0)
|
||||
{
|
||||
}
|
||||
|
||||
StringT(const char* _rhs)
|
||||
{
|
||||
clear();
|
||||
|
||||
if (NULL != _rhs)
|
||||
{
|
||||
uint32_t len = strlen(_rhs);
|
||||
m_len = len;
|
||||
if (0 != len)
|
||||
{
|
||||
++len;
|
||||
|
||||
char* ptr = (char*)BX_ALLOC(*allocator, len);
|
||||
|
||||
memcpy(ptr, _rhs, len);
|
||||
|
||||
*const_cast<char**>(&m_ptr) = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringT(const StringView& _str)
|
||||
{
|
||||
uint32_t len = _str.getLength();
|
||||
m_len = len;
|
||||
if (0 != len)
|
||||
{
|
||||
++len;
|
||||
|
||||
char* ptr = (char*)BX_ALLOC(*allocator, len);
|
||||
|
||||
memcpy(ptr, _str.getPtr(), len-1);
|
||||
ptr[len] = '\0';
|
||||
|
||||
*const_cast<char**>(&m_ptr) = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
~StringT()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (0 != m_len)
|
||||
{
|
||||
BX_FREE(*allocator, const_cast<char*>(m_ptr) );
|
||||
|
||||
StringView::clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
inline bool toBool(const char* _str)
|
||||
{
|
||||
|
||||
@@ -692,6 +692,46 @@ namespace bx
|
||||
#endif // BX_COMPILER_
|
||||
}
|
||||
|
||||
inline uint64_t uint64_sll(uint64_t _a, int _sa)
|
||||
{
|
||||
return _a << _sa;
|
||||
}
|
||||
|
||||
inline uint64_t uint64_srl(uint64_t _a, int _sa)
|
||||
{
|
||||
return _a >> _sa;
|
||||
}
|
||||
|
||||
inline uint64_t uint64_sra(uint64_t _a, int _sa)
|
||||
{
|
||||
return ( (int64_t)_a) >> _sa;
|
||||
}
|
||||
|
||||
inline uint64_t uint64_rol(uint64_t _a, int _sa)
|
||||
{
|
||||
return ( _a << _sa) | (_a >> (32-_sa) );
|
||||
}
|
||||
|
||||
inline uint64_t uint64_ror(uint64_t _a, int _sa)
|
||||
{
|
||||
return ( _a >> _sa) | (_a << (32-_sa) );
|
||||
}
|
||||
|
||||
inline uint64_t uint64_add(uint64_t _a, uint64_t _b)
|
||||
{
|
||||
return _a + _b;
|
||||
}
|
||||
|
||||
inline uint64_t uint64_sub(uint64_t _a, uint64_t _b)
|
||||
{
|
||||
return _a - _b;
|
||||
}
|
||||
|
||||
inline uint64_t uint64_mul(uint64_t _a, uint64_t _b)
|
||||
{
|
||||
return _a * _b;
|
||||
}
|
||||
|
||||
/// Greatest common divisor.
|
||||
inline uint32_t uint32_gcd(uint32_t _a, uint32_t _b)
|
||||
{
|
||||
|
||||
@@ -49,8 +49,64 @@ project "bx.test"
|
||||
}
|
||||
|
||||
files {
|
||||
path.join(BX_DIR, "tests/**.cpp"),
|
||||
path.join(BX_DIR, "tests/**.H"),
|
||||
path.join(BX_DIR, "tests/*_test.cpp"),
|
||||
path.join(BX_DIR, "tests/*_test.H"),
|
||||
path.join(BX_DIR, "tests/dbg.*"),
|
||||
}
|
||||
|
||||
configuration { "vs* or mingw*" }
|
||||
links {
|
||||
"psapi",
|
||||
}
|
||||
|
||||
configuration { "android*" }
|
||||
targetextension ".so"
|
||||
linkoptions {
|
||||
"-shared",
|
||||
}
|
||||
|
||||
configuration { "nacl or nacl-arm" }
|
||||
targetextension ".nexe"
|
||||
links {
|
||||
"ppapi",
|
||||
"pthread",
|
||||
}
|
||||
|
||||
configuration { "pnacl" }
|
||||
targetextension ".pexe"
|
||||
links {
|
||||
"ppapi",
|
||||
"pthread",
|
||||
}
|
||||
|
||||
configuration { "linux-*" }
|
||||
links {
|
||||
"pthread",
|
||||
}
|
||||
|
||||
configuration { "osx" }
|
||||
links {
|
||||
"Cocoa.framework",
|
||||
}
|
||||
|
||||
configuration {}
|
||||
|
||||
strip()
|
||||
|
||||
project "bx.bench"
|
||||
kind "ConsoleApp"
|
||||
|
||||
debugdir (path.join(BX_DIR, "tests"))
|
||||
|
||||
includedirs {
|
||||
path.join(BX_DIR, "include"),
|
||||
BX_THIRD_PARTY_DIR,
|
||||
}
|
||||
|
||||
files {
|
||||
path.join(BX_DIR, "tests/*_bench.cpp"),
|
||||
path.join(BX_DIR, "tests/*_bench.h"),
|
||||
path.join(BX_DIR, "tests/dbg.*"),
|
||||
}
|
||||
|
||||
configuration { "vs* or mingw*" }
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Branimir Karadzic. All rights reserved.
|
||||
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include <bx/handlealloc.h>
|
||||
|
||||
TEST(HandleListT)
|
||||
{
|
||||
bx::HandleListT<32> list;
|
||||
|
||||
list.pushBack(16);
|
||||
CHECK(list.getFront() == 16);
|
||||
CHECK(list.getBack() == 16);
|
||||
|
||||
list.pushFront(7);
|
||||
CHECK(list.getFront() == 7);
|
||||
CHECK(list.getBack() == 16);
|
||||
|
||||
uint16_t expected0[] = { 15, 31, 7, 16, 17, 11, 13 };
|
||||
list.pushBack(17);
|
||||
list.pushBack(11);
|
||||
list.pushBack(13);
|
||||
list.pushFront(31);
|
||||
list.pushFront(15);
|
||||
uint16_t count = 0;
|
||||
for (uint16_t it = list.getFront(); it != UINT16_MAX; it = list.getNext(it), ++count)
|
||||
{
|
||||
CHECK(it == expected0[count]);
|
||||
}
|
||||
CHECK(count == BX_COUNTOF(expected0) );
|
||||
|
||||
list.remove(17);
|
||||
list.remove(31);
|
||||
list.remove(16);
|
||||
list.pushBack(16);
|
||||
uint16_t expected1[] = { 15, 7, 11, 13, 16 };
|
||||
count = 0;
|
||||
for (uint16_t it = list.getFront(); it != UINT16_MAX; it = list.getNext(it), ++count)
|
||||
{
|
||||
CHECK(it == expected1[count]);
|
||||
}
|
||||
CHECK(count == BX_COUNTOF(expected1) );
|
||||
|
||||
list.popBack();
|
||||
list.popFront();
|
||||
list.popBack();
|
||||
list.popBack();
|
||||
|
||||
CHECK(list.getFront() == 7);
|
||||
CHECK(list.getBack() == 7);
|
||||
|
||||
list.popBack();
|
||||
CHECK(list.getFront() == UINT16_MAX);
|
||||
CHECK(list.getBack() == UINT16_MAX);
|
||||
}
|
||||
|
||||
TEST(HandleAllocLruT)
|
||||
{
|
||||
bx::HandleAllocLruT<16> lru;
|
||||
|
||||
uint16_t handle[4] =
|
||||
{
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
};
|
||||
|
||||
lru.touch(handle[1]);
|
||||
|
||||
uint16_t expected0[] = { handle[1], handle[3], handle[2], handle[0] };
|
||||
uint16_t count = 0;
|
||||
for (uint16_t it = lru.getFront(); it != UINT16_MAX; it = lru.getNext(it), ++count)
|
||||
{
|
||||
CHECK(it == expected0[count]);
|
||||
}
|
||||
}
|
||||
76
tests/handle_bench.cpp
Normal file
76
tests/handle_bench.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <bx/bx.h>
|
||||
#include <bx/timer.h>
|
||||
#include <bx/handlealloc.h>
|
||||
|
||||
#include <tinystl/allocator.h>
|
||||
#include <tinystl/unordered_map.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
const uint32_t numElements = 4<<10;
|
||||
const uint32_t numIterations = 16;
|
||||
|
||||
//
|
||||
{
|
||||
int64_t elapsed = -bx::getHPCounter();
|
||||
|
||||
for (uint32_t ii = 0; ii < numIterations; ++ii)
|
||||
{
|
||||
typedef tinystl::unordered_map<uint64_t, uint16_t> TinyStlUnorderedMap;
|
||||
TinyStlUnorderedMap map;
|
||||
for (uint32_t jj = 0; jj < numElements; ++jj)
|
||||
{
|
||||
tinystl::pair<TinyStlUnorderedMap::iterator, bool> ok = map.insert(tinystl::make_pair(uint64_t(jj), uint16_t(jj) ) );
|
||||
assert(ok.second);
|
||||
}
|
||||
}
|
||||
|
||||
elapsed += bx::getHPCounter();
|
||||
printf(" TinyStl: %15f\n", double(elapsed) );
|
||||
}
|
||||
|
||||
///
|
||||
{
|
||||
int64_t elapsed = -bx::getHPCounter();
|
||||
|
||||
for (uint32_t ii = 0; ii < numIterations; ++ii)
|
||||
{
|
||||
typedef std::unordered_map<uint64_t, uint16_t> StdUnorderedMap;
|
||||
StdUnorderedMap map;
|
||||
for (uint32_t jj = 0; jj < numElements; ++jj)
|
||||
{
|
||||
std::pair<StdUnorderedMap::iterator, bool> ok = map.insert(std::make_pair(uint64_t(jj), uint16_t(jj) ) );
|
||||
assert(ok.second);
|
||||
}
|
||||
}
|
||||
|
||||
elapsed += bx::getHPCounter();
|
||||
printf(" STL: %15f\n", double(elapsed) );
|
||||
}
|
||||
|
||||
///
|
||||
{
|
||||
int64_t elapsed = -bx::getHPCounter();
|
||||
|
||||
for (uint32_t ii = 0; ii < numIterations; ++ii)
|
||||
{
|
||||
typedef bx::HandleHashMapT<numElements+numElements/2, uint64_t> HandleHashMap;
|
||||
HandleHashMap map;
|
||||
for (uint32_t jj = 0; jj < numElements; ++jj)
|
||||
{
|
||||
bool ok = map.insert(jj, uint16_t(jj) );
|
||||
assert(ok);
|
||||
}
|
||||
}
|
||||
|
||||
elapsed += bx::getHPCounter();
|
||||
printf("HandleHashMap: %15f\n", double(elapsed) );
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
119
tests/handle_test.cpp
Normal file
119
tests/handle_test.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Branimir Karadzic. All rights reserved.
|
||||
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include <bx/handlealloc.h>
|
||||
#include <bx/string.h>
|
||||
|
||||
TEST_CASE("HandleListT", "")
|
||||
{
|
||||
bx::HandleListT<32> list;
|
||||
|
||||
list.pushBack(16);
|
||||
REQUIRE(list.getFront() == 16);
|
||||
REQUIRE(list.getBack() == 16);
|
||||
|
||||
list.pushFront(7);
|
||||
REQUIRE(list.getFront() == 7);
|
||||
REQUIRE(list.getBack() == 16);
|
||||
|
||||
uint16_t expected0[] = { 15, 31, 7, 16, 17, 11, 13 };
|
||||
list.pushBack(17);
|
||||
list.pushBack(11);
|
||||
list.pushBack(13);
|
||||
list.pushFront(31);
|
||||
list.pushFront(15);
|
||||
uint16_t count = 0;
|
||||
for (uint16_t it = list.getFront(); it != UINT16_MAX; it = list.getNext(it), ++count)
|
||||
{
|
||||
REQUIRE(it == expected0[count]);
|
||||
}
|
||||
REQUIRE(count == BX_COUNTOF(expected0) );
|
||||
|
||||
list.remove(17);
|
||||
list.remove(31);
|
||||
list.remove(16);
|
||||
list.pushBack(16);
|
||||
uint16_t expected1[] = { 15, 7, 11, 13, 16 };
|
||||
count = 0;
|
||||
for (uint16_t it = list.getFront(); it != UINT16_MAX; it = list.getNext(it), ++count)
|
||||
{
|
||||
REQUIRE(it == expected1[count]);
|
||||
}
|
||||
REQUIRE(count == BX_COUNTOF(expected1) );
|
||||
|
||||
list.popBack();
|
||||
list.popFront();
|
||||
list.popBack();
|
||||
list.popBack();
|
||||
|
||||
REQUIRE(list.getFront() == 7);
|
||||
REQUIRE(list.getBack() == 7);
|
||||
|
||||
list.popBack();
|
||||
REQUIRE(list.getFront() == UINT16_MAX);
|
||||
REQUIRE(list.getBack() == UINT16_MAX);
|
||||
}
|
||||
|
||||
TEST_CASE("HandleAllocLruT", "")
|
||||
{
|
||||
bx::HandleAllocLruT<16> lru;
|
||||
|
||||
uint16_t handle[4] =
|
||||
{
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
lru.alloc(),
|
||||
};
|
||||
|
||||
lru.touch(handle[1]);
|
||||
|
||||
uint16_t expected0[] = { handle[1], handle[3], handle[2], handle[0] };
|
||||
uint16_t count = 0;
|
||||
for (uint16_t it = lru.getFront(); it != UINT16_MAX; it = lru.getNext(it), ++count)
|
||||
{
|
||||
REQUIRE(it == expected0[count]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("HandleHashTable", "")
|
||||
{
|
||||
typedef bx::HandleHashMapT<512> HashMap;
|
||||
|
||||
HashMap hm;
|
||||
|
||||
REQUIRE(512 == hm.getMaxCapacity() );
|
||||
|
||||
bx::StringView sv0("test0");
|
||||
|
||||
bool ok = hm.insert(bx::hashMurmur2A(sv0), 0);
|
||||
REQUIRE(ok);
|
||||
|
||||
ok = hm.insert(bx::hashMurmur2A(sv0), 0);
|
||||
REQUIRE(!ok);
|
||||
REQUIRE(1 == hm.getNumElements() );
|
||||
|
||||
bx::StringView sv1("test1");
|
||||
|
||||
ok = hm.insert(bx::hashMurmur2A(sv1), 0);
|
||||
REQUIRE(ok);
|
||||
REQUIRE(2 == hm.getNumElements() );
|
||||
|
||||
hm.removeByHandle(0);
|
||||
REQUIRE(0 == hm.getNumElements() );
|
||||
|
||||
ok = hm.insert(bx::hashMurmur2A(sv0), 0);
|
||||
REQUIRE(ok);
|
||||
|
||||
hm.removeByKey(bx::hashMurmur2A(sv0) );
|
||||
REQUIRE(0 == hm.getNumElements() );
|
||||
|
||||
for (uint32_t ii = 0, num = hm.getMaxCapacity(); ii < num; ++ii)
|
||||
{
|
||||
ok = hm.insert(ii, uint16_t(ii) );
|
||||
REQUIRE(ok);
|
||||
}
|
||||
}
|
||||
32
tests/string_test.cpp
Normal file
32
tests/string_test.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2016 Branimir Karadzic. All rights reserved.
|
||||
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include <bx/string.h>
|
||||
#include <bx/crtimpl.h>
|
||||
#include <bx/handlealloc.h>
|
||||
|
||||
bx::AllocatorI* g_allocator;
|
||||
|
||||
TEST_CASE("StringView", "")
|
||||
{
|
||||
bx::StringView sv("test");
|
||||
REQUIRE(4 == sv.getLength() );
|
||||
|
||||
bx::CrtAllocator crt;
|
||||
g_allocator = &crt;
|
||||
|
||||
typedef bx::StringT<&g_allocator> String;
|
||||
|
||||
String st(sv);
|
||||
REQUIRE(4 == st.getLength() );
|
||||
|
||||
st.clear();
|
||||
REQUIRE(0 == st.getLength() );
|
||||
REQUIRE(4 == sv.getLength() );
|
||||
|
||||
sv.clear();
|
||||
REQUIRE(0 == sv.getLength() );
|
||||
}
|
||||
Reference in New Issue
Block a user