summaryrefslogtreecommitdiff
path: root/thirdparty/basis_universal/transcoder/basisu_containers_impl.h
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2021-05-07 17:00:41 +0200
committerRémi Verschelde <rverschelde@gmail.com>2021-05-07 17:26:11 +0200
commit2d133177e979bd68eba1a241cae84a8215087993 (patch)
tree94fb2234bca62d156054b772802087ede2db01fd /thirdparty/basis_universal/transcoder/basisu_containers_impl.h
parent8976594f4b90edd42a926e483815c829a540d8d2 (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.h311
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