Utility.cppm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. module;
  2. #include <new>
  3. export module Core.Utility;
  4. export import Core.Types;
  5. import Core.Meta;
  6. import Core.Std;
  7. #define SOURCE const std::source_location& l = std::source_location::current()
  8. export namespace std {
  9. using std::source_location;
  10. }
  11. #ifdef CHECK_MEMORY
  12. export void* operator new(size_t count, const std::source_location& l) noexcept;
  13. export void* operator new[](
  14. size_t count, const std::source_location& l) noexcept;
  15. #endif
  16. export namespace Core {
  17. template<typename T, typename C = int>
  18. C popCount(const T& t) noexcept {
  19. static constexpr C map[16] = {0, 1, 1, 2, 1, 2, 2, 3,
  20. 1, 2, 2, 3, 2, 3, 3, 4};
  21. C sum = 0;
  22. for(size_t i = 0; i < sizeof(T) * 8; i += 4) {
  23. sum += map[(t >> i) & 0xF];
  24. }
  25. return sum;
  26. }
  27. using ExitHandler = void (*)(int, void*);
  28. [[noreturn]] void exitWithHandler(int value, SOURCE) noexcept;
  29. void setExitHandler(ExitHandler h, void* data) noexcept;
  30. using OutOfMemoryHandler = void (*)(void*);
  31. void setOutOfMemoryHandler(OutOfMemoryHandler h, void* data) noexcept;
  32. #ifdef CHECK_MEMORY
  33. void* allocateRaw(size_t n, SOURCE) noexcept;
  34. void* zeroAllocateRaw(size_t n, SOURCE) noexcept;
  35. void* reallocateRaw(void* p, size_t n, SOURCE) noexcept;
  36. void deallocateRaw(void* p, SOURCE) noexcept;
  37. template<typename T, typename... Args>
  38. T* newWithSource(Args&&... args) noexcept {
  39. static_assert(noexcept(new(std::source_location::current())
  40. T(Core::forward<Args>(args)...)));
  41. return new(std::source_location::current())
  42. T(Core::forward<Args>(args)...);
  43. }
  44. template<typename T>
  45. T* newWithSourceN(size_t n) noexcept {
  46. // GCC does not realize this is noexcept, ...
  47. // checking the empty constructor instead
  48. #if defined(__GNUC__) && !defined(__clang__)
  49. static_assert(noexcept(new(std::source_location::current()) T()));
  50. #else
  51. static_assert(noexcept(new(std::source_location::current()) T[n]));
  52. #endif
  53. return new(std::source_location::current()) T[n];
  54. }
  55. #else
  56. void* allocateRaw(size_t n) noexcept;
  57. void* zeroAllocateRaw(size_t n) noexcept;
  58. void* reallocateRaw(void* p, size_t n) noexcept;
  59. void deallocateRaw(void* p) noexcept;
  60. template<typename T, typename... Args>
  61. T* newWithSource(Args&&... args) noexcept {
  62. static_assert(
  63. noexcept(new(std::nothrow) T(Core::forward<Args>(args)...)));
  64. return new(std::nothrow) T(Core::forward<Args>(args)...);
  65. }
  66. template<typename T>
  67. T* newWithSourceN(size_t n) noexcept {
  68. static_assert(noexcept(new(std::nothrow) T[n]));
  69. return new(std::nothrow) T[n];
  70. }
  71. #endif
  72. void printMemoryReport() noexcept;
  73. template<typename T>
  74. void deleteWithSource(T* p) noexcept {
  75. delete p;
  76. }
  77. template<typename T>
  78. void deleteWithSourceN(T* p) noexcept {
  79. delete[] p;
  80. }
  81. template<typename T>
  82. void bubbleSort(T* data, size_t n) noexcept {
  83. bool swapped = true;
  84. while(swapped && n > 0) {
  85. swapped = false;
  86. n--;
  87. for(size_t i = 0; i < n; i++) {
  88. if(data[i] > data[i + 1]) {
  89. swap(data[i], data[i + 1]);
  90. swapped = true;
  91. }
  92. }
  93. }
  94. }
  95. }