#include "core/utils/Utility.hpp" #include #include #include #include "ErrorSimulator.hpp" #include "core/utils/Error.hpp" #include "core/utils/Logger.hpp" static Core::ExitHandler exitHandler = nullptr; static void* exitData = nullptr; static Core::OutOfMemoryHandler outOfMemoryHandler = nullptr; static void* outOfMemoryData = nullptr; void Core::exitWithHandler(const char* file, int line, int value) { if(value != 0) { printf("%sExit from %s:%d with value %d%s\n", Core::Logger::COLOR_RED, Core::Logger::getFileName(file), line, value, Core::Logger::COLOR_RESET); } if(exitHandler != nullptr) { exitHandler(value, exitData); } exit(value); } void Core::setExitHandler(ExitHandler eh, void* data) { exitHandler = eh; exitData = data; } #define CORE_TO_STRING(type, cast, format) \ size_t Core::toString(type t, char* buffer, size_t size) { \ int w = snprintf(buffer, size, format, static_cast(t)); \ return w < 0 ? 0 : static_cast(w); \ } CORE_TO_STRING(signed short, signed short, "%hd") CORE_TO_STRING(unsigned short, unsigned short, "%hu") CORE_TO_STRING(signed int, signed int, "%d") CORE_TO_STRING(unsigned int, unsigned int, "%u") CORE_TO_STRING(signed long, signed long, "%ld") CORE_TO_STRING(unsigned long, unsigned long, "%lu") CORE_TO_STRING(signed long long, signed long long, "%lld") CORE_TO_STRING(unsigned long long, unsigned long long, "%llu") CORE_TO_STRING(float, double, "%.2f") CORE_TO_STRING(double, double, "%.2lf") CORE_TO_STRING(long double, long double, "%.2Lf") void Core::print(int c) { if(putchar(c) < 0) { CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore } } void Core::print(const char* s) { if(fputs(s, stdout) < 0) { CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore } } void Core::printLine(const char* s) { if(puts(s) < 0) { CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore } } void Core::setOutOfMemoryHandler(OutOfMemoryHandler h, void* data) { outOfMemoryHandler = h; outOfMemoryData = data; } void* Core::allocate(size_t n) { // deny too large allocations instantly // this makes LTO happy if(n >= 1024lu * 1024lu * 1024lu * 64lu) { CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore } void* p = malloc(n); #ifdef ERROR_SIMULATOR if(CORE_ALLOC_FAIL && p != nullptr) { free(p); p = nullptr; } #endif while(p == nullptr && outOfMemoryHandler != nullptr) { outOfMemoryHandler(outOfMemoryData); p = malloc(n); } if(p == nullptr) { CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore } return p; } void* Core::reallocate(void* oldP, size_t n) { if(n <= 0) { free(oldP); return nullptr; } void* p = realloc(oldP, n); #ifdef ERROR_SIMULATOR if(CORE_ALLOC_FAIL && p != nullptr) { oldP = p; p = nullptr; } #endif // this double check is to prevent the compiler from complaining if(p == nullptr) { while(p == nullptr && outOfMemoryHandler != nullptr) { outOfMemoryHandler(outOfMemoryData); p = realloc(oldP, n); } } if(p == nullptr) { CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore } return p; }