basisu_containers_impl.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // basisu_containers_impl.h
  2. // Do not include directly
  3. #ifdef _MSC_VER
  4. #pragma warning (disable:4127) // warning C4127: conditional expression is constant
  5. #endif
  6. namespace basisu
  7. {
  8. bool elemental_vector::increase_capacity(uint32_t min_new_capacity, bool grow_hint, uint32_t element_size, object_mover pMover, bool nofail)
  9. {
  10. assert(m_size <= m_capacity);
  11. if (sizeof(void *) == sizeof(uint64_t))
  12. assert(min_new_capacity < (0x400000000ULL / element_size));
  13. else
  14. assert(min_new_capacity < (0x7FFF0000U / element_size));
  15. if (m_capacity >= min_new_capacity)
  16. return true;
  17. size_t new_capacity = min_new_capacity;
  18. if ((grow_hint) && (!helpers::is_power_of_2((uint64_t)new_capacity)))
  19. {
  20. new_capacity = (size_t)helpers::next_pow2((uint64_t)new_capacity);
  21. assert(new_capacity && (new_capacity > m_capacity));
  22. if (new_capacity < min_new_capacity)
  23. {
  24. if (nofail)
  25. return false;
  26. fprintf(stderr, "vector too large\n");
  27. abort();
  28. }
  29. }
  30. const size_t desired_size = element_size * new_capacity;
  31. size_t actual_size = 0;
  32. if (!pMover)
  33. {
  34. void* new_p = realloc(m_p, desired_size);
  35. if (!new_p)
  36. {
  37. if (nofail)
  38. return false;
  39. char buf[256];
  40. #ifdef _MSC_VER
  41. sprintf_s(buf, sizeof(buf), "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
  42. #else
  43. sprintf(buf, "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
  44. #endif
  45. fprintf(stderr, "%s", buf);
  46. abort();
  47. }
  48. #if BASISU_VECTOR_DETERMINISTIC
  49. actual_size = desired_size;
  50. #elif defined(_MSC_VER)
  51. actual_size = _msize(new_p);
  52. #elif HAS_MALLOC_USABLE_SIZE
  53. actual_size = malloc_usable_size(new_p);
  54. #else
  55. actual_size = desired_size;
  56. #endif
  57. m_p = new_p;
  58. }
  59. else
  60. {
  61. void* new_p = malloc(desired_size);
  62. if (!new_p)
  63. {
  64. if (nofail)
  65. return false;
  66. char buf[256];
  67. #ifdef _MSC_VER
  68. sprintf_s(buf, sizeof(buf), "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
  69. #else
  70. sprintf(buf, "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
  71. #endif
  72. fprintf(stderr, "%s", buf);
  73. abort();
  74. }
  75. #if BASISU_VECTOR_DETERMINISTIC
  76. actual_size = desired_size;
  77. #elif defined(_MSC_VER)
  78. actual_size = _msize(new_p);
  79. #elif HAS_MALLOC_USABLE_SIZE
  80. actual_size = malloc_usable_size(new_p);
  81. #else
  82. actual_size = desired_size;
  83. #endif
  84. (*pMover)(new_p, m_p, m_size);
  85. if (m_p)
  86. free(m_p);
  87. m_p = new_p;
  88. }
  89. if (actual_size > desired_size)
  90. m_capacity = static_cast<uint32_t>(actual_size / element_size);
  91. else
  92. m_capacity = static_cast<uint32_t>(new_capacity);
  93. return true;
  94. }
  95. #if BASISU_HASHMAP_TEST
  96. #define HASHMAP_TEST_VERIFY(c) do { if (!(c)) handle_hashmap_test_verify_failure(__LINE__); } while(0)
  97. static void handle_hashmap_test_verify_failure(int line)
  98. {
  99. fprintf(stderr, "HASHMAP_TEST_VERIFY() faild on line %i\n", line);
  100. abort();
  101. }
  102. class counted_obj
  103. {
  104. public:
  105. counted_obj(uint32_t v = 0) :
  106. m_val(v)
  107. {
  108. m_count++;
  109. }
  110. counted_obj(const counted_obj& obj) :
  111. m_val(obj.m_val)
  112. {
  113. m_count++;
  114. }
  115. ~counted_obj()
  116. {
  117. assert(m_count > 0);
  118. m_count--;
  119. }
  120. static uint32_t m_count;
  121. uint32_t m_val;
  122. operator size_t() const { return m_val; }
  123. bool operator== (const counted_obj& rhs) const { return m_val == rhs.m_val; }
  124. bool operator== (const uint32_t rhs) const { return m_val == rhs; }
  125. };
  126. uint32_t counted_obj::m_count;
  127. static uint32_t urand32()
  128. {
  129. uint32_t a = rand();
  130. uint32_t b = rand() << 15;
  131. uint32_t c = rand() << (32 - 15);
  132. return a ^ b ^ c;
  133. }
  134. static int irand32(int l, int h)
  135. {
  136. assert(l < h);
  137. if (l >= h)
  138. return l;
  139. uint32_t range = static_cast<uint32_t>(h - l);
  140. uint32_t rnd = urand32();
  141. uint32_t rnd_range = static_cast<uint32_t>((((uint64_t)range) * ((uint64_t)rnd)) >> 32U);
  142. int result = l + rnd_range;
  143. assert((result >= l) && (result < h));
  144. return result;
  145. }
  146. void hash_map_test()
  147. {
  148. {
  149. basisu::hash_map<uint64_t, uint64_t> k;
  150. basisu::hash_map<uint64_t, uint64_t> l;
  151. std::swap(k, l);
  152. k.begin();
  153. k.end();
  154. k.clear();
  155. k.empty();
  156. k.erase(0);
  157. k.insert(0, 1);
  158. k.find(0);
  159. k.get_equals();
  160. k.get_hasher();
  161. k.get_table_size();
  162. k.reset();
  163. k.reserve(1);
  164. k = l;
  165. k.set_equals(l.get_equals());
  166. k.set_hasher(l.get_hasher());
  167. k.get_table_size();
  168. }
  169. uint32_t seed = 0;
  170. for (; ; )
  171. {
  172. seed++;
  173. typedef basisu::hash_map<counted_obj, counted_obj> my_hash_map;
  174. my_hash_map m;
  175. const uint32_t n = irand32(0, 100000);
  176. printf("%u\n", n);
  177. srand(seed); // r1.seed(seed);
  178. basisu::vector<int> q;
  179. uint32_t count = 0;
  180. for (uint32_t i = 0; i < n; i++)
  181. {
  182. uint32_t v = urand32() & 0x7FFFFFFF;
  183. my_hash_map::insert_result res = m.insert(counted_obj(v), counted_obj(v ^ 0xdeadbeef));
  184. if (res.second)
  185. {
  186. count++;
  187. q.push_back(v);
  188. }
  189. }
  190. HASHMAP_TEST_VERIFY(m.size() == count);
  191. srand(seed);
  192. my_hash_map cm(m);
  193. m.clear();
  194. m = cm;
  195. cm.reset();
  196. for (uint32_t i = 0; i < n; i++)
  197. {
  198. uint32_t v = urand32() & 0x7FFFFFFF;
  199. my_hash_map::const_iterator it = m.find(counted_obj(v));
  200. HASHMAP_TEST_VERIFY(it != m.end());
  201. HASHMAP_TEST_VERIFY(it->first == v);
  202. HASHMAP_TEST_VERIFY(it->second == (v ^ 0xdeadbeef));
  203. }
  204. for (uint32_t t = 0; t < 2; t++)
  205. {
  206. const uint32_t nd = irand32(1, q.size() + 1);
  207. for (uint32_t i = 0; i < nd; i++)
  208. {
  209. uint32_t p = irand32(0, q.size());
  210. int k = q[p];
  211. if (k >= 0)
  212. {
  213. q[p] = -k - 1;
  214. bool s = m.erase(counted_obj(k));
  215. HASHMAP_TEST_VERIFY(s);
  216. }
  217. }
  218. typedef basisu::hash_map<uint32_t, empty_type> uint_hash_set;
  219. uint_hash_set s;
  220. for (uint32_t i = 0; i < q.size(); i++)
  221. {
  222. int v = q[i];
  223. if (v >= 0)
  224. {
  225. my_hash_map::const_iterator it = m.find(counted_obj(v));
  226. HASHMAP_TEST_VERIFY(it != m.end());
  227. HASHMAP_TEST_VERIFY(it->first == (uint32_t)v);
  228. HASHMAP_TEST_VERIFY(it->second == ((uint32_t)v ^ 0xdeadbeef));
  229. s.insert(v);
  230. }
  231. else
  232. {
  233. my_hash_map::const_iterator it = m.find(counted_obj(-v - 1));
  234. HASHMAP_TEST_VERIFY(it == m.end());
  235. }
  236. }
  237. uint32_t found_count = 0;
  238. for (my_hash_map::const_iterator it = m.begin(); it != m.end(); ++it)
  239. {
  240. HASHMAP_TEST_VERIFY(it->second == ((uint32_t)it->first ^ 0xdeadbeef));
  241. uint_hash_set::const_iterator fit(s.find((uint32_t)it->first));
  242. HASHMAP_TEST_VERIFY(fit != s.end());
  243. HASHMAP_TEST_VERIFY(fit->first == it->first);
  244. found_count++;
  245. }
  246. HASHMAP_TEST_VERIFY(found_count == s.size());
  247. }
  248. HASHMAP_TEST_VERIFY(counted_obj::m_count == m.size() * 2);
  249. }
  250. }
  251. #endif // BASISU_HASHMAP_TEST
  252. } // namespace basisu