q_std.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. #pragma once
  4. // q_std.h -- 'standard' library stuff for game module
  5. // not meant to be included by engine, etc
  6. #include <cmath>
  7. #include <cstdio>
  8. #include <cstdarg>
  9. #include <cstring>
  10. #include <cstdlib>
  11. #include <cstddef>
  12. #include <cinttypes>
  13. #include <ctime>
  14. #include <type_traits>
  15. #include <algorithm>
  16. #include <array>
  17. #include <string_view>
  18. #include <numeric>
  19. #include <functional>
  20. // format!
  21. #ifndef USE_CPP20_FORMAT
  22. #ifdef __cpp_lib_format
  23. #define USE_CPP20_FORMAT 1
  24. #endif
  25. #endif
  26. #if USE_CPP20_FORMAT
  27. #include <format>
  28. namespace fmt = std;
  29. #define FMT_STRING(s) s
  30. #else
  31. #include <fmt/format.h>
  32. #endif
  33. struct g_fmt_data_t {
  34. char string[2][4096];
  35. int istr;
  36. };
  37. // static data for fmt; internal, do not touch
  38. extern g_fmt_data_t g_fmt_data;
  39. // like fmt::format_to_n, but automatically null terminates the output;
  40. // returns the length of the string written (up to N)
  41. #ifdef USE_CPP20_FORMAT
  42. #define G_FmtTo_ G_FmtTo
  43. template<size_t N, typename... Args>
  44. inline size_t G_FmtTo(char (&buffer)[N], std::format_string<Args...> format_str, Args &&... args)
  45. #else
  46. #define G_FmtTo(buffer, str, ...) \
  47. G_FmtTo_(buffer, FMT_STRING(str), __VA_ARGS__)
  48. template<size_t N, typename S, typename... Args>
  49. inline size_t G_FmtTo_(char (&buffer)[N], const S &format_str, Args &&... args)
  50. #endif
  51. {
  52. auto end = fmt::format_to_n(buffer, N - 1, format_str, std::forward<Args>(args)...);
  53. *(end.out) = '\0';
  54. return end.out - buffer;
  55. }
  56. // format to temp buffers; doesn't use heap allocation
  57. // unlike `fmt::format` does directly
  58. #ifdef USE_CPP20_FORMAT
  59. template<typename... Args>
  60. [[nodiscard]] inline std::string_view G_Fmt(std::format_string<Args...> format_str, Args &&... args)
  61. #else
  62. #define G_Fmt(str, ...) \
  63. G_Fmt_(FMT_STRING(str), __VA_ARGS__)
  64. template<typename S, typename... Args>
  65. [[nodiscard]] inline std::string_view G_Fmt_(const S &format_str, Args &&... args)
  66. #endif
  67. {
  68. g_fmt_data.istr ^= 1;
  69. size_t len = G_FmtTo_(g_fmt_data.string[g_fmt_data.istr], format_str, std::forward<Args>(args)...);
  70. return std::string_view(g_fmt_data.string[g_fmt_data.istr], len);
  71. }
  72. // fmt::join replacement
  73. template<typename T>
  74. std::string join_strings(const T &cont, const char *separator)
  75. {
  76. if (cont.empty())
  77. return "";
  78. return std::accumulate(++cont.begin(), cont.end(), *cont.begin(),
  79. [separator](auto &&a, auto &&b) -> auto & {
  80. a += separator;
  81. a += b;
  82. return a;
  83. });
  84. }
  85. using byte = uint8_t;
  86. // note: only works on actual arrays
  87. #define q_countof(a) std::extent_v<decltype(a)>
  88. using std::max;
  89. using std::min;
  90. using std::clamp;
  91. template<typename T>
  92. constexpr T lerp(T from, T to, float t)
  93. {
  94. return (to * t) + (from * (1.f - t));
  95. }
  96. // angle indexes
  97. enum
  98. {
  99. PITCH,
  100. YAW,
  101. ROLL
  102. };
  103. /*
  104. ==============================================================
  105. MATHLIB
  106. ==============================================================
  107. */
  108. constexpr double PI = 3.14159265358979323846; // matches value in gcc v2 math.h
  109. constexpr float PIf = static_cast<float>(PI);
  110. [[nodiscard]] constexpr float RAD2DEG(float x)
  111. {
  112. return (x * 180.0f / PIf);
  113. }
  114. [[nodiscard]] constexpr float DEG2RAD(float x)
  115. {
  116. return (x * PIf / 180.0f);
  117. }
  118. /*
  119. =============
  120. G_AddBlend
  121. =============
  122. */
  123. inline void G_AddBlend(float r, float g, float b, float a, std::array<float, 4> &v_blend)
  124. {
  125. if (a <= 0)
  126. return;
  127. float a2 = v_blend[3] + (1 - v_blend[3]) * a; // new total alpha
  128. float a3 = v_blend[3] / a2; // fraction of color from old
  129. v_blend[0] = v_blend[0] * a3 + r * (1 - a3);
  130. v_blend[1] = v_blend[1] * a3 + g * (1 - a3);
  131. v_blend[2] = v_blend[2] * a3 + b * (1 - a3);
  132. v_blend[3] = a2;
  133. }
  134. //============================================================================
  135. /*
  136. ===============
  137. LerpAngle
  138. ===============
  139. */
  140. [[nodiscard]] constexpr float LerpAngle(float a2, float a1, float frac)
  141. {
  142. if (a1 - a2 > 180)
  143. a1 -= 360;
  144. if (a1 - a2 < -180)
  145. a1 += 360;
  146. return a2 + frac * (a1 - a2);
  147. }
  148. [[nodiscard]] inline float anglemod(float a)
  149. {
  150. float v = fmod(a, 360.0f);
  151. if (v < 0)
  152. return 360.f + v;
  153. return v;
  154. }
  155. #include "q_vec3.h"
  156. //=============================================
  157. char *COM_ParseEx(const char **data_p, const char *seps, char *buffer = nullptr, size_t buffer_size = 0);
  158. // data is an in/out parm, returns a parsed out token
  159. inline char *COM_Parse(const char **data_p, char *buffer = nullptr, size_t buffer_size = 0)
  160. {
  161. return COM_ParseEx(data_p, "\r\n\t ", buffer, buffer_size);
  162. }
  163. //=============================================
  164. // portable case insensitive compare
  165. [[nodiscard]] int Q_strcasecmp(const char *s1, const char *s2);
  166. [[nodiscard]] int Q_strncasecmp(const char *s1, const char *s2, size_t n);
  167. // BSD string utils - haleyjd
  168. size_t Q_strlcpy(char* dst, const char* src, size_t siz);
  169. size_t Q_strlcat(char* dst, const char* src, size_t siz);
  170. // EOF