General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.1 KiB

пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
  1. #pragma once
  2. #include <stddef.h>
  3. #include "gp_config.hpp"
  4. #include "gp/algorithm/move.hpp"
  5. #include "gp/iterator.hpp"
  6. #include "gp/array.hpp"
  7. namespace gp{
  8. template<typename T, size_t _capacity>
  9. class indexed_array{
  10. size_t data_top = 0;
  11. size_t available_indexes_top = 0;
  12. size_t remove_top = 0;
  13. gp::array<char, sizeof(T)*_capacity> data_table;
  14. size_t available_indexes[_capacity];
  15. size_t translation_table[_capacity];
  16. size_t reverse_translation_table[_capacity];
  17. size_t remove_table[_capacity];
  18. public:
  19. indexed_array() {}
  20. size_t push(T&& value) {
  21. size_t index;
  22. gp_config::assertion(data_top+1 != _capacity, "Indexed array capacity exceeded");
  23. if(available_indexes_top) {
  24. available_indexes_top--;
  25. index = available_indexes[available_indexes_top];
  26. } else {
  27. index = data_top;
  28. }
  29. new(&(data_table.as_buffer().template cast<T>()[data_top])) T(gp::move(value));
  30. translation_table[index] = data_top;
  31. reverse_translation_table[data_top] = index;
  32. ++data_top;
  33. return index;
  34. }
  35. void pop(size_t idx) {
  36. size_t v_idx = translation_table[idx];
  37. available_indexes[available_indexes_top] = idx;
  38. ++available_indexes_top;
  39. translation_table[idx] = -1;
  40. --data_top;
  41. if(v_idx < data_top) {
  42. size_t u_idx = reverse_translation_table[data_top];
  43. data_table.as_buffer().template cast<T>()[v_idx] = gp::move(data_table[data_top]);
  44. ::operator delete(&data_table.as_buffer().template cast<T>()[data_top], &(data_table.as_buffer().template cast<T>()[data_top]));
  45. data_table.as_buffer().template cast<T>()[data_top].~T();
  46. translation_table[u_idx] = v_idx;
  47. reverse_translation_table[v_idx] = u_idx;
  48. }
  49. }
  50. void reset() {
  51. auto it = data_table;
  52. auto end = data_table+data_top;
  53. while(it != end) {
  54. ::operator delete(it, it);
  55. ++it;
  56. }
  57. data_top = 0;
  58. available_indexes_top = 0;
  59. remove_top = 0;
  60. }
  61. void mark_internal_for_removal(size_t i_idx) {
  62. remove_table[remove_top] = reverse_translation_table[i_idx];
  63. ++remove_top;
  64. }
  65. void mark_for_removal(size_t idx) {
  66. remove_table[remove_top] = idx;
  67. ++remove_top;
  68. }
  69. void sweep_removed() {
  70. auto it = remove_table;
  71. auto end = remove_table+remove_top;
  72. while(it != end) {
  73. pop(*it);
  74. ++it;
  75. }
  76. }
  77. bool has(size_t idx) {
  78. if(idx > data_top) return false;
  79. if(translation_table[idx] == -1) return false;
  80. return true;
  81. }
  82. pointer_iterator<T> begin()
  83. {
  84. return data_table.as_buffer().template cast<T>().begin();
  85. }
  86. pointer_iterator<T> end()
  87. {
  88. return data_table.as_buffer().template cast<T>().begin()+data_top;
  89. }
  90. const_pointer_iterator<T> cbegin()
  91. {
  92. return data_table.as_buffer().template cast<T>().cbegin();
  93. }
  94. const_pointer_iterator<T> cend()
  95. {
  96. return data_table.as_buffer().template cast<T>().cbegin()+data_top;
  97. }
  98. size_t size() {
  99. return data_top;
  100. }
  101. size_t capacity() {
  102. return _capacity;
  103. }
  104. T& operator[](size_t idx) {
  105. gp_config::assertion(idx < data_top, "Bad indexed array access");
  106. return data_table.as_buffer().template cast<T>()[translation_table[idx]];
  107. }
  108. };
  109. }