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.

123 lines
3.1KB

  1. #pragma once
  2. // Include some of the C++ standard library for convenience
  3. #include <cstdlib>
  4. #include <cstdio>
  5. #include <cstdint>
  6. #include <cstdarg>
  7. #include <climits>
  8. #include <cmath>
  9. #include <cstring>
  10. #include <cassert>
  11. #include <string>
  12. /** Deprecation notice for GCC */
  13. #define DEPRECATED __attribute__ ((deprecated))
  14. /** Concatenates two literals or two macros
  15. Example:
  16. #define COUNT 42
  17. CONCAT(myVariable, COUNT)
  18. expands to
  19. myVariable42
  20. */
  21. #define CONCAT_LITERAL(x, y) x ## y
  22. #define CONCAT(x, y) CONCAT_LITERAL(x, y)
  23. /** Surrounds raw text with quotes
  24. Example:
  25. #define NAME "world"
  26. printf("Hello " TOSTRING(NAME))
  27. expands to
  28. printf("Hello " "world")
  29. and of course the C++ lexer/parser then concatenates the string literals.
  30. */
  31. #define TOSTRING_LITERAL(x) #x
  32. #define TOSTRING(x) TOSTRING_LITERAL(x)
  33. /** Produces the length of a static array in number of elements */
  34. #define LENGTHOF(arr) (sizeof(arr) / sizeof((arr)[0]))
  35. /** Reserve space for `count` enums starting with `name`.
  36. Example:
  37. enum Foo {
  38. ENUMS(BAR, 14),
  39. BAZ
  40. };
  41. BAR + 0 to BAR + 13 is reserved. BAZ has a value of 14.
  42. */
  43. #define ENUMS(name, count) name, name ## _LAST = name + (count) - 1
  44. /** References binary files compiled into the program.
  45. For example, to include a file "Test.dat" directly into your program binary, add
  46. BINARIES += Test.dat
  47. to your Makefile and declare
  48. BINARY(Test_dat);
  49. at the root of a .c or .cpp source file. Note that special characters are replaced with "_". Then use
  50. BINARY_START(Test_dat)
  51. BINARY_END(Test_dat)
  52. to reference the data beginning and end as a void* array, and
  53. BINARY_SIZE(Test_dat)
  54. to get its size in bytes.
  55. */
  56. #ifdef ARCH_MAC
  57. // Use output from `xxd -i`
  58. #define BINARY(sym) extern unsigned char sym[]; extern unsigned int sym##_len
  59. #define BINARY_START(sym) ((const void*) sym)
  60. #define BINARY_END(sym) ((const void*) sym + sym##_len)
  61. #define BINARY_SIZE(sym) (sym##_len)
  62. #else
  63. #define BINARY(sym) extern char _binary_##sym##_start, _binary_##sym##_end, _binary_##sym##_size
  64. #define BINARY_START(sym) ((const void*) &_binary_##sym##_start)
  65. #define BINARY_END(sym) ((const void*) &_binary_##sym##_end)
  66. // The symbol "_binary_##sym##_size" doesn't seem to be valid after a plugin is dynamically loaded, so simply take the difference between the two addresses.
  67. #define BINARY_SIZE(sym) ((size_t) (&_binary_##sym##_end - &_binary_##sym##_start))
  68. #endif
  69. /** C#-style property constructor
  70. Example:
  71. Foo *foo = construct<Foo>(&Foo::greeting, "Hello world", &Foo::legs, 2);
  72. */
  73. template<typename T>
  74. T *construct() {
  75. return new T();
  76. }
  77. template<typename T, typename F, typename V, typename... Args>
  78. T *construct(F f, V v, Args... args) {
  79. T *o = construct<T>(args...);
  80. o->*f = v;
  81. return o;
  82. }
  83. /** Defers code until the scope is destructed
  84. From http://www.gingerbill.org/article/defer-in-cpp.html
  85. Example:
  86. file = fopen(...);
  87. DEFER({
  88. fclose(file);
  89. });
  90. */
  91. template<typename F>
  92. struct DeferWrapper {
  93. F f;
  94. DeferWrapper(F f) : f(f) {}
  95. ~DeferWrapper() { f(); }
  96. };
  97. template<typename F>
  98. DeferWrapper<F> deferWrapper(F f) {
  99. return DeferWrapper<F>(f);
  100. }
  101. #define DEFER(code) auto CONCAT(_defer_, __COUNTER__) = deferWrapper([&]() code)