module; #include #include export module Core.Utility; import Core.Meta; #define SOURCE const std::source_location& l = std::source_location::current() export namespace std { using std::source_location; } #ifdef CHECK_MEMORY export void* operator new(size_t count, const std::source_location& l); export void* operator new[](size_t count, const std::source_location& l); #endif export namespace Core { template C popCount(const T& t) { static constexpr C map[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; C sum = 0; for(size_t i = 0; i < sizeof(T) * 8; i += 4) { sum += map[(t >> i) & 0xF]; } return sum; } using ExitHandler = void (*)(int, void*); [[noreturn]] void exitWithHandler(int value, SOURCE); void setExitHandler(ExitHandler h, void* data); using OutOfMemoryHandler = void (*)(void*); void setOutOfMemoryHandler(OutOfMemoryHandler h, void* data); #ifdef CHECK_MEMORY void* allocateRaw(size_t n, SOURCE); void* zeroAllocateRaw(size_t n, SOURCE); void* reallocateRaw(void* p, size_t n, SOURCE); void deallocateRaw(void* p, SOURCE); template T* newWithSource(Args&&... args) { return new(std::source_location::current()) T(Core::forward(args)...); } template T* newWithSourceN(size_t n) { return new(std::source_location::current()) T[n]; } #else void* allocateRaw(size_t n); void* zeroAllocateRaw(size_t n); void* reallocateRaw(void* p, size_t n); void deallocateRaw(void* p); template T* newWithSource(Args&&... args) { return new T(Core::forward(args)...); } template T* newWithSourceN(size_t n) { return new T[n]; } #endif void printMemoryReport(); template void deleteWithSource(T* p) { delete p; } template void deleteWithSourceN(T* p) { delete[] p; } template void bubbleSort(T* data, size_t n) { bool swapped = true; while(swapped && n > 0) { swapped = false; n--; for(size_t i = 0; i < n; i++) { if(data[i] > data[i + 1]) { swap(data[i], data[i + 1]); swapped = true; } } } } }