diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2021-05-07 17:00:41 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2021-05-07 17:26:11 +0200 |
commit | 2d133177e979bd68eba1a241cae84a8215087993 (patch) | |
tree | 94fb2234bca62d156054b772802087ede2db01fd /thirdparty/basis_universal/transcoder/basisu_containers_impl.h | |
parent | 8976594f4b90edd42a926e483815c829a540d8d2 (diff) |
basis_universal: Update to upstream commit from Apr 16, 2021
BinomialLLC/basis_universal@ba1c3e40f1d434ebaf9a167b44e9b11d2bf0f765.
Diffstat (limited to 'thirdparty/basis_universal/transcoder/basisu_containers_impl.h')
-rw-r--r-- | thirdparty/basis_universal/transcoder/basisu_containers_impl.h | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/thirdparty/basis_universal/transcoder/basisu_containers_impl.h b/thirdparty/basis_universal/transcoder/basisu_containers_impl.h new file mode 100644 index 0000000000..6555171419 --- /dev/null +++ b/thirdparty/basis_universal/transcoder/basisu_containers_impl.h @@ -0,0 +1,311 @@ +// basisu_containers_impl.h +// Do not include directly + +#ifdef _MSC_VER +#pragma warning (disable:4127) // warning C4127: conditional expression is constant +#endif + +namespace basisu +{ + bool elemental_vector::increase_capacity(uint32_t min_new_capacity, bool grow_hint, uint32_t element_size, object_mover pMover, bool nofail) + { + assert(m_size <= m_capacity); + + if (sizeof(void *) == sizeof(uint64_t)) + assert(min_new_capacity < (0x400000000ULL / element_size)); + else + assert(min_new_capacity < (0x7FFF0000U / element_size)); + + if (m_capacity >= min_new_capacity) + return true; + + size_t new_capacity = min_new_capacity; + if ((grow_hint) && (!helpers::is_power_of_2((uint64_t)new_capacity))) + { + new_capacity = (size_t)helpers::next_pow2((uint64_t)new_capacity); + + assert(new_capacity && (new_capacity > m_capacity)); + + if (new_capacity < min_new_capacity) + { + if (nofail) + return false; + fprintf(stderr, "vector too large\n"); + abort(); + } + } + + const size_t desired_size = element_size * new_capacity; + size_t actual_size = 0; + if (!pMover) + { + void* new_p = realloc(m_p, desired_size); + if (!new_p) + { + if (nofail) + return false; + + char buf[256]; +#ifdef _MSC_VER + sprintf_s(buf, sizeof(buf), "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size); +#else + sprintf(buf, "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size); +#endif + fprintf(stderr, "%s", buf); + abort(); + } + +#ifdef _MSC_VER + actual_size = _msize(new_p); +#elif HAS_MALLOC_USABLE_SIZE + actual_size = malloc_usable_size(new_p); +#else + actual_size = desired_size; +#endif + m_p = new_p; + } + else + { + void* new_p = malloc(desired_size); + if (!new_p) + { + if (nofail) + return false; + + char buf[256]; +#ifdef _MSC_VER + sprintf_s(buf, sizeof(buf), "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size); +#else + sprintf(buf, "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size); +#endif + fprintf(stderr, "%s", buf); + abort(); + } + +#ifdef _MSC_VER + actual_size = _msize(new_p); +#elif HAS_MALLOC_USABLE_SIZE + actual_size = malloc_usable_size(new_p); +#else + actual_size = desired_size; +#endif + + (*pMover)(new_p, m_p, m_size); + + if (m_p) + free(m_p); + + m_p = new_p; + } + + if (actual_size > desired_size) + m_capacity = static_cast<uint32_t>(actual_size / element_size); + else + m_capacity = static_cast<uint32_t>(new_capacity); + + return true; + } + +#if BASISU_HASHMAP_TEST + +#define HASHMAP_TEST_VERIFY(c) do { if (!(c)) handle_hashmap_test_verify_failure(__LINE__); } while(0) + + static void handle_hashmap_test_verify_failure(int line) + { + fprintf(stderr, "HASHMAP_TEST_VERIFY() faild on line %i\n", line); + abort(); + } + + class counted_obj + { + public: + counted_obj(uint32_t v = 0) : + m_val(v) + { + m_count++; + } + + counted_obj(const counted_obj& obj) : + m_val(obj.m_val) + { + m_count++; + } + + ~counted_obj() + { + assert(m_count > 0); + m_count--; + } + + static uint32_t m_count; + + uint32_t m_val; + + operator size_t() const { return m_val; } + + bool operator== (const counted_obj& rhs) const { return m_val == rhs.m_val; } + bool operator== (const uint32_t rhs) const { return m_val == rhs; } + + }; + + uint32_t counted_obj::m_count; + + static uint32_t urand32() + { + uint32_t a = rand(); + uint32_t b = rand() << 15; + uint32_t c = rand() << (32 - 15); + return a ^ b ^ c; + } + + static int irand32(int l, int h) + { + assert(l < h); + if (l >= h) + return l; + + uint32_t range = static_cast<uint32_t>(h - l); + + uint32_t rnd = urand32(); + + uint32_t rnd_range = static_cast<uint32_t>((((uint64_t)range) * ((uint64_t)rnd)) >> 32U); + + int result = l + rnd_range; + assert((result >= l) && (result < h)); + return result; + } + + void hash_map_test() + { + { + basisu::hash_map<uint64_t, uint64_t> k; + basisu::hash_map<uint64_t, uint64_t> l; + std::swap(k, l); + + k.begin(); + k.end(); + k.clear(); + k.empty(); + k.erase(0); + k.insert(0, 1); + k.find(0); + k.get_equals(); + k.get_hasher(); + k.get_table_size(); + k.reset(); + k.reserve(1); + k = l; + k.set_equals(l.get_equals()); + k.set_hasher(l.get_hasher()); + k.get_table_size(); + } + + uint32_t seed = 0; + for (; ; ) + { + seed++; + + typedef basisu::hash_map<counted_obj, counted_obj> my_hash_map; + my_hash_map m; + + const uint32_t n = irand32(0, 100000); + + printf("%u\n", n); + + srand(seed); // r1.seed(seed); + + basisu::vector<int> q; + + uint32_t count = 0; + for (uint32_t i = 0; i < n; i++) + { + uint32_t v = urand32() & 0x7FFFFFFF; + my_hash_map::insert_result res = m.insert(counted_obj(v), counted_obj(v ^ 0xdeadbeef)); + if (res.second) + { + count++; + q.push_back(v); + } + } + + HASHMAP_TEST_VERIFY(m.size() == count); + + srand(seed); + + my_hash_map cm(m); + m.clear(); + m = cm; + cm.reset(); + + for (uint32_t i = 0; i < n; i++) + { + uint32_t v = urand32() & 0x7FFFFFFF; + my_hash_map::const_iterator it = m.find(counted_obj(v)); + HASHMAP_TEST_VERIFY(it != m.end()); + HASHMAP_TEST_VERIFY(it->first == v); + HASHMAP_TEST_VERIFY(it->second == (v ^ 0xdeadbeef)); + } + + for (uint32_t t = 0; t < 2; t++) + { + const uint32_t nd = irand32(1, q.size() + 1); + for (uint32_t i = 0; i < nd; i++) + { + uint32_t p = irand32(0, q.size()); + + int k = q[p]; + if (k >= 0) + { + q[p] = -k - 1; + + bool s = m.erase(counted_obj(k)); + HASHMAP_TEST_VERIFY(s); + } + } + + typedef basisu::hash_map<uint32_t, empty_type> uint_hash_set; + uint_hash_set s; + + for (uint32_t i = 0; i < q.size(); i++) + { + int v = q[i]; + + if (v >= 0) + { + my_hash_map::const_iterator it = m.find(counted_obj(v)); + HASHMAP_TEST_VERIFY(it != m.end()); + HASHMAP_TEST_VERIFY(it->first == (uint32_t)v); + HASHMAP_TEST_VERIFY(it->second == ((uint32_t)v ^ 0xdeadbeef)); + + s.insert(v); + } + else + { + my_hash_map::const_iterator it = m.find(counted_obj(-v - 1)); + HASHMAP_TEST_VERIFY(it == m.end()); + } + } + + uint32_t found_count = 0; + for (my_hash_map::const_iterator it = m.begin(); it != m.end(); ++it) + { + HASHMAP_TEST_VERIFY(it->second == ((uint32_t)it->first ^ 0xdeadbeef)); + + uint_hash_set::const_iterator fit(s.find((uint32_t)it->first)); + HASHMAP_TEST_VERIFY(fit != s.end()); + + HASHMAP_TEST_VERIFY(fit->first == it->first); + + found_count++; + } + + HASHMAP_TEST_VERIFY(found_count == s.size()); + } + + HASHMAP_TEST_VERIFY(counted_obj::m_count == m.size() * 2); + } + } + +#endif // BASISU_HASHMAP_TEST + +} // namespace basisu |