Browse Source

Added HandleHashMap.

Branimir Karadžić 9 years ago
parent
commit
5fe975a39b

+ 292 - 0
include/bx/handlealloc.h

@@ -8,9 +8,11 @@
 
 
 #include "bx.h"
 #include "bx.h"
 #include "allocator.h"
 #include "allocator.h"
+#include "uint32_t.h"
 
 
 namespace bx
 namespace bx
 {
 {
+	///
 	class HandleAlloc
 	class HandleAlloc
 	{
 	{
 	public:
 	public:
@@ -127,6 +129,7 @@ namespace bx
 		BX_FREE(_allocator, _handleAlloc);
 		BX_FREE(_allocator, _handleAlloc);
 	}
 	}
 
 
+	///
 	template <uint16_t MaxHandlesT>
 	template <uint16_t MaxHandlesT>
 	class HandleAllocT : public HandleAlloc
 	class HandleAllocT : public HandleAlloc
 	{
 	{
@@ -144,6 +147,7 @@ namespace bx
 		uint16_t m_padding[2*MaxHandlesT];
 		uint16_t m_padding[2*MaxHandlesT];
 	};
 	};
 
 
+	///
 	template <uint16_t MaxHandlesT>
 	template <uint16_t MaxHandlesT>
 	class HandleListT
 	class HandleListT
 	{
 	{
@@ -327,6 +331,7 @@ namespace bx
 		Link m_links[MaxHandlesT];
 		Link m_links[MaxHandlesT];
 	};
 	};
 
 
+	///
 	template <uint16_t MaxHandlesT>
 	template <uint16_t MaxHandlesT>
 	class HandleAllocLruT
 	class HandleAllocLruT
 	{
 	{
@@ -422,6 +427,293 @@ namespace bx
 		HandleAllocT<MaxHandlesT> m_alloc;
 		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
 } // namespace bx
 
 
 #endif // BX_HANDLE_ALLOC_H_HEADER_GUARD
 #endif // BX_HANDLE_ALLOC_H_HEADER_GUARD

+ 1 - 0
include/bx/hash.h

@@ -162,6 +162,7 @@ namespace bx
 	template <typename Ty>
 	template <typename Ty>
 	inline uint32_t hashMurmur2A(const Ty& _data)
 	inline uint32_t hashMurmur2A(const Ty& _data)
 	{
 	{
+		BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) );
 		return hashMurmur2A(&_data, sizeof(Ty) );
 		return hashMurmur2A(&_data, sizeof(Ty) );
 	}
 	}
 
 

+ 134 - 0
include/bx/string.h

@@ -14,12 +14,146 @@
 #include <string.h>
 #include <string.h>
 #include <wchar.h>  // wchar_t
 #include <wchar.h>  // wchar_t
 
 
+#include <bx/allocator.h>
+#include <bx/hash.h>
+
 #ifndef va_copy
 #ifndef va_copy
 #	define va_copy(_a, _b) (_a) = (_b)
 #	define va_copy(_a, _b) (_a) = (_b)
 #endif // va_copy
 #endif // va_copy
 
 
 namespace bx
 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)
 	inline bool toBool(const char* _str)
 	{
 	{

+ 40 - 0
include/bx/uint32_t.h

@@ -692,6 +692,46 @@ namespace bx
 #endif // BX_COMPILER_
 #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.
 	/// Greatest common divisor.
 	inline uint32_t uint32_gcd(uint32_t _a, uint32_t _b)
 	inline uint32_t uint32_gcd(uint32_t _a, uint32_t _b)
 	{
 	{

+ 58 - 2
scripts/genie.lua

@@ -49,8 +49,64 @@ project "bx.test"
 	}
 	}
 
 
 	files {
 	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*" }
 	configuration { "vs* or mingw*" }

+ 0 - 0
tests/fpumath.cpp → tests/fpumath_test.cpp


+ 0 - 79
tests/handle.cpp

@@ -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 - 0
tests/handle_bench.cpp

@@ -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 - 0
tests/handle_test.cpp

@@ -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);
+	}
+}

+ 0 - 0
tests/macros.cpp → tests/macros_test.cpp


+ 0 - 0
tests/main.cpp → tests/main_test.cpp


+ 0 - 0
tests/misc.cpp → tests/misc_test.cpp


+ 0 - 0
tests/simd_t.cpp → tests/simd_test.cpp


+ 32 - 0
tests/string_test.cpp

@@ -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() );
+}

+ 0 - 0
tests/thread.cpp → tests/thread_test.cpp


+ 0 - 0
tests/tokenizecmd.cpp → tests/tokenizecmd_test.cpp


+ 0 - 0
tests/uint32_t.cpp → tests/uint32_test.cpp


+ 0 - 0
tests/unordered_map_nonpod.cpp → tests/unordered_map_nonpod_test.cpp


+ 0 - 0
tests/unordered_set_copyctor.cpp → tests/unordered_set_copyctor_test.cpp


+ 0 - 0
tests/unordered_set_pod.cpp → tests/unordered_set_pod_test.cpp


+ 0 - 0
tests/vector_complex.cpp → tests/vector_complex_test.cpp


+ 0 - 0
tests/vector_header.cpp → tests/vector_header_test.cpp


+ 0 - 0
tests/vector_nocopy.cpp → tests/vector_nocopy_test.cpp


+ 0 - 0
tests/vector_nodefault.cpp → tests/vector_nodefault_test.cpp


+ 0 - 0
tests/vector_primitive.cpp → tests/vector_primitive_test.cpp


+ 0 - 0
tests/vector_shrinktofit.cpp → tests/vector_shrinktofit_test.cpp