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.

195 lines
4.4KB

  1. #pragma once
  2. // Include most of the C standard library for convenience
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <string>
  9. #include <condition_variable>
  10. #include <mutex>
  11. ////////////////////
  12. // Handy macros
  13. ////////////////////
  14. /** Surrounds raw text with quotes
  15. Example:
  16. printf("Hello " STRINGIFY(world))
  17. will expand to
  18. printf("Hello " "world")
  19. and of course the C++ lexer/parser will then concatenate the string literals
  20. */
  21. #define STRINGIFY(x) #x
  22. /** Converts a macro to a string literal
  23. Example:
  24. #define NAME "world"
  25. printf("Hello " TOSTRING(NAME))
  26. will expand to
  27. printf("Hello " "world")
  28. */
  29. #define TOSTRING(x) STRINGIFY(x)
  30. #define LENGTHOF(arr) (sizeof(arr) / sizeof((arr)[0]))
  31. /** Reserve space for `count` enums starting with `name`.
  32. Example:
  33. enum Foo {
  34. ENUMS(BAR, 14),
  35. BAZ
  36. };
  37. BAR + 0 to BAR + 13 is reserved. BAZ has a value of 14.
  38. */
  39. #define ENUMS(name, count) name, name ## _LAST = name + (count) - 1
  40. /** Deprecation notice for GCC */
  41. #define DEPRECATED __attribute__ ((deprecated))
  42. #include "util/math.hpp"
  43. namespace rack {
  44. ////////////////////
  45. // Template hacks
  46. ////////////////////
  47. /** C#-style property constructor
  48. Example:
  49. Foo *foo = construct<Foo>(&Foo::greeting, "Hello world");
  50. */
  51. template<typename T>
  52. T *construct() {
  53. return new T();
  54. }
  55. template<typename T, typename F, typename V, typename... Args>
  56. T *construct(F f, V v, Args... args) {
  57. T *o = construct<T>(args...);
  58. o->*f = v;
  59. return o;
  60. }
  61. /** Defers code until the scope is destructed
  62. From http://www.gingerbill.org/article/defer-in-cpp.html
  63. Example:
  64. file = fopen(...);
  65. defer({
  66. fclose(file);
  67. });
  68. */
  69. template <typename F>
  70. struct DeferWrapper {
  71. F f;
  72. DeferWrapper(F f) : f(f) {}
  73. ~DeferWrapper() { f(); }
  74. };
  75. template <typename F>
  76. DeferWrapper<F> deferWrapper(F f) {
  77. return DeferWrapper<F>(f);
  78. }
  79. #define DEFER_1(x, y) x##y
  80. #define DEFER_2(x, y) DEFER_1(x, y)
  81. #define DEFER_3(x) DEFER_2(x, __COUNTER__)
  82. #define defer(code) auto DEFER_3(_defer_) = deferWrapper([&]() code)
  83. ////////////////////
  84. // Random number generator
  85. // random.cpp
  86. ////////////////////
  87. /** Seeds the RNG with the current time */
  88. void randomInit();
  89. uint32_t randomu32();
  90. uint64_t randomu64();
  91. /** Returns a uniform random float in the interval [0.0, 1.0) */
  92. float randomUniform();
  93. /** Returns a normal random number with mean 0 and std dev 1 */
  94. float randomNormal();
  95. inline float DEPRECATED randomf() {return randomUniform();}
  96. ////////////////////
  97. // String utilities
  98. // string.cpp
  99. ////////////////////
  100. /** Converts a printf format string and optional arguments into a std::string */
  101. std::string stringf(const char *format, ...);
  102. std::string lowercase(std::string s);
  103. std::string uppercase(std::string s);
  104. /** Truncates and adds "..." to a string, not exceeding `len` characters */
  105. std::string ellipsize(std::string s, size_t len);
  106. bool startsWith(std::string str, std::string prefix);
  107. std::string extractDirectory(std::string path);
  108. std::string extractFilename(std::string path);
  109. std::string extractExtension(std::string path);
  110. ////////////////////
  111. // Operating-system specific utilities
  112. // system.cpp
  113. ////////////////////
  114. /** Opens a URL, also happens to work with PDFs and folders.
  115. Shell injection is possible, so make sure the URL is trusted or hard coded.
  116. May block, so open in a new thread.
  117. */
  118. void openBrowser(std::string url);
  119. ////////////////////
  120. // Debug logger
  121. // logger.cpp
  122. ////////////////////
  123. extern FILE *gLogFile;
  124. void debug(const char *format, ...);
  125. void info(const char *format, ...);
  126. void warn(const char *format, ...);
  127. void fatal(const char *format, ...);
  128. ////////////////////
  129. // Thread functions
  130. ////////////////////
  131. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  132. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  133. */
  134. struct VIPMutex {
  135. int count = 0;
  136. std::condition_variable cv;
  137. std::mutex countMutex;
  138. /** Blocks until there are no remaining VIPLocks */
  139. void wait() {
  140. std::unique_lock<std::mutex> lock(countMutex);
  141. while (count > 0)
  142. cv.wait(lock);
  143. }
  144. };
  145. struct VIPLock {
  146. VIPMutex &m;
  147. VIPLock(VIPMutex &m) : m(m) {
  148. std::unique_lock<std::mutex> lock(m.countMutex);
  149. m.count++;
  150. }
  151. ~VIPLock() {
  152. std::unique_lock<std::mutex> lock(m.countMutex);
  153. m.count--;
  154. lock.unlock();
  155. m.cv.notify_all();
  156. }
  157. };
  158. } // namespace rack