Utility.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include "core/utils/Utility.hpp"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "ErrorSimulator.hpp"
  6. #include "core/utils/Error.hpp"
  7. #include "core/utils/Logger.hpp"
  8. static Core::ExitHandler exitHandler = nullptr;
  9. static void* exitData = nullptr;
  10. static Core::OutOfMemoryHandler outOfMemoryHandler = nullptr;
  11. static void* outOfMemoryData = nullptr;
  12. void Core::exitWithHandler(const char* file, int line, int value) {
  13. if(value != 0) {
  14. printf("%sExit from %s:%d with value %d%s\n", Core::Logger::COLOR_RED,
  15. Core::Logger::getFileName(file), line, value,
  16. Core::Logger::COLOR_RESET);
  17. }
  18. if(exitHandler != nullptr) {
  19. exitHandler(value, exitData);
  20. }
  21. exit(value);
  22. }
  23. void Core::setExitHandler(ExitHandler eh, void* data) {
  24. exitHandler = eh;
  25. exitData = data;
  26. }
  27. #define CORE_TO_STRING(type, cast, format) \
  28. size_t Core::toString(type t, char* buffer, size_t size) { \
  29. int w = snprintf(buffer, size, format, static_cast<cast>(t)); \
  30. return w < 0 ? 0 : static_cast<size_t>(w); \
  31. }
  32. CORE_TO_STRING(signed short, signed short, "%hd")
  33. CORE_TO_STRING(unsigned short, unsigned short, "%hu")
  34. CORE_TO_STRING(signed int, signed int, "%d")
  35. CORE_TO_STRING(unsigned int, unsigned int, "%u")
  36. CORE_TO_STRING(signed long, signed long, "%ld")
  37. CORE_TO_STRING(unsigned long, unsigned long, "%lu")
  38. CORE_TO_STRING(signed long long, signed long long, "%lld")
  39. CORE_TO_STRING(unsigned long long, unsigned long long, "%llu")
  40. CORE_TO_STRING(float, double, "%.2f")
  41. CORE_TO_STRING(double, double, "%.2lf")
  42. CORE_TO_STRING(long double, long double, "%.2Lf")
  43. void Core::print(int c) {
  44. if(putchar(c) < 0) {
  45. CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore
  46. }
  47. }
  48. void Core::print(const char* s) {
  49. if(fputs(s, stdout) < 0) {
  50. CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore
  51. }
  52. }
  53. void Core::printLine(const char* s) {
  54. if(puts(s) < 0) {
  55. CORE_EXIT(ErrorCode::BLOCKED_STDOUT.code); // CoverageIgnore
  56. }
  57. }
  58. void Core::setOutOfMemoryHandler(OutOfMemoryHandler h, void* data) {
  59. outOfMemoryHandler = h;
  60. outOfMemoryData = data;
  61. }
  62. void* Core::allocate(size_t n) {
  63. // deny too large allocations instantly
  64. // this makes LTO happy
  65. if(n >= 1024lu * 1024lu * 1024lu * 64lu) {
  66. CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore
  67. }
  68. void* p = malloc(n);
  69. #ifdef ERROR_SIMULATOR
  70. if(CORE_ALLOC_FAIL && p != nullptr) {
  71. free(p);
  72. p = nullptr;
  73. }
  74. #endif
  75. while(p == nullptr && outOfMemoryHandler != nullptr) {
  76. outOfMemoryHandler(outOfMemoryData);
  77. p = malloc(n);
  78. }
  79. if(p == nullptr) {
  80. CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore
  81. }
  82. return p;
  83. }
  84. void* Core::reallocate(void* oldP, size_t n) {
  85. if(n <= 0) {
  86. free(oldP);
  87. return nullptr;
  88. }
  89. void* p = realloc(oldP, n);
  90. #ifdef ERROR_SIMULATOR
  91. if(CORE_ALLOC_FAIL && p != nullptr) {
  92. oldP = p;
  93. p = nullptr;
  94. }
  95. #endif
  96. // this double check is to prevent the compiler from complaining
  97. if(p == nullptr) {
  98. while(p == nullptr && outOfMemoryHandler != nullptr) {
  99. outOfMemoryHandler(outOfMemoryData);
  100. p = realloc(oldP, n);
  101. }
  102. }
  103. if(p == nullptr) {
  104. CORE_EXIT(ErrorCode::OUT_OF_MEMORY.code); // CoverageIgnore
  105. }
  106. return p;
  107. }