Pioneer
utils.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _UTILS_H
5 #define _UTILS_H
6 
7 #if defined(_MSC_VER) && !defined(NOMINMAX)
8 #define NOMINMAX
9 #endif
10 
11 #include "core/Log.h"
12 #include "libs.h"
13 #include <fmt/printf.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <string>
17 #include <vector>
18 
19 #ifndef __GNUC__
20 #define __attribute(x)
21 #endif /* __GNUC__ */
22 
23 // GCC warns when a function marked __attribute((noreturn)) actually returns a value
24 // but other compilers which don't see the noreturn attribute of course require that
25 // a function with a non-void return type should return something.
26 #ifndef __GNUC__
27 #define RETURN_ZERO_NONGNU_ONLY return 0;
28 #else
29 #define RETURN_ZERO_NONGNU_ONLY
30 #endif
31 
32 // align x to a. taken from the Linux kernel
33 #define ALIGN(x, a) __ALIGN_MASK(x, (a - 1))
34 #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
35 
36 // void Error(const char *format, ...) __attribute((format(printf, 1, 2))) __attribute((noreturn));
37 // void Warning(const char *format, ...) __attribute((format(printf, 1, 2)));
38 // void Output(const char *format, ...) __attribute((format(printf, 1, 2)));
39 
40 template <typename... Args>
41 inline void Output(const char *message, Args... args)
42 {
43  Log::LogOld(Log::Severity::Info, fmt::sprintf(message, args...));
44 }
45 
46 template <typename... Args>
47 inline void Warning(const char *message, Args... args)
48 {
49  Log::LogOld(Log::Severity::Warning, fmt::sprintf(message, args...));
50 }
51 
52 template <typename... Args>
53 [[noreturn]] inline void Error(const char *message, Args... args)
54 {
55  Log::LogFatalOld(fmt::sprintf(message, args...));
56 }
57 
58 template <typename... Args>
59 inline void DebugMsg(const char *message, Args... args)
60 {
61  Log::LogOld(Log::Severity::Debug, fmt::sprintf(message, args...));
62 }
63 
64 std::string string_join(std::vector<std::string> &v, std::string sep);
65 std::string format_date(double time);
66 std::string format_date_only(double time);
67 std::string format_distance(double dist, int precision = 2);
68 std::string format_money(double cents, bool showCents = true);
69 std::string format_duration(double seconds);
70 
71 static inline Sint64 isqrt(Sint64 a)
72 {
73  // replace with cast from sqrt below which is between x7.3 (win32, Debug) & x15 (x64, Release) times faster
74  return static_cast<int64_t>(sqrt(static_cast<double>(a)));
75 }
76 
77 static inline Sint64 isqrt(fixed v)
78 {
79  Sint64 ret = 0;
80  Sint64 s;
81  Sint64 ret_sq = -v.v - 1;
82  for (s = 62; s >= 0; s -= 2) {
83  Sint64 b;
84  ret += ret;
85  b = ret_sq + ((2 * ret + 1) << s);
86  if (b < 0) {
87  ret_sq = b;
88  ret++;
89  }
90  }
91  return ret;
92 }
93 
94 // find string in bigger string, ignoring case
95 const char *pi_strcasestr(const char *haystack, const char *needle);
96 
97 inline bool starts_with(const std::string_view s, const std::string_view t)
98 {
99  if (s.size() < t.size())
100  return false;
101  return memcmp(s.data(), t.data(), t.size()) == 0;
102 }
103 
104 inline bool ends_with(const std::string_view s, const std::string_view t)
105 {
106  if (s.size() < t.size())
107  return false;
108 
109  return memcmp(s.data() + (s.size() - t.size()), t.data(), t.size()) == 0;
110 }
111 
112 inline bool starts_with_ci(const std::string_view s, const std::string_view t)
113 {
114  if (s.size() < t.size())
115  return false;
116 
117  for (size_t i = 0; i < t.size(); i++)
118  if (tolower(s.data()[i]) != tolower(t.data()[i]))
119  return false;
120 
121  return true;
122 }
123 
124 inline bool ends_with_ci(const std::string_view s, const std::string_view t)
125 {
126  if (s.size() < t.size())
127  return false;
128 
129  for (int64_t i = t.size(); i > 0; i--)
130  if (tolower(s.data()[s.size() - i]) != tolower(t.data()[t.size() - i]))
131  return false;
132 
133  return true;
134 }
135 
136 inline bool compare_ci(const std::string_view s, const std::string_view t)
137 {
138  if (s.size() != t.size())
139  return false;
140 
141  for (size_t i = 0; i < s.size(); i++)
142  if (tolower(s.data()[i]) != tolower(t.data()[i]))
143  return false;
144 
145  return true;
146 }
147 
148 inline std::string_view read_line(std::string_view &s)
149 {
150  if (s.empty())
151  return {};
152 
153  std::string_view out = s;
154 
155  size_t end = s.find_first_of("\r\n");
156  if (end == std::string_view::npos) {
157  s = {};
158  return out;
159  }
160 
161  out = { s.data(), end };
162 
163  size_t start = s.find_first_not_of("\r\n", end);
164  if (start == std::string_view::npos) {
165  s = {};
166  return out;
167  }
168 
169  s.remove_prefix(start);
170  return out;
171 }
172 
173 inline std::string_view strip_spaces(std::string_view &s)
174 {
175  if (s.empty())
176  return s;
177 
178  size_t start = s.find_first_not_of(" \t\r\n\v");
179  if (start == std::string::npos)
180  return {};
181 
182  size_t end = s.find_last_not_of(" \t\r\n\v");
183 
184  return s.substr(start, end);
185 }
186 
187 static inline size_t SplitSpec(const std::string &spec, std::vector<int> &output)
188 {
189  static const std::string delim(",");
190 
191  size_t i = 0, start = 0, end = 0;
192  while (end != std::string::npos) {
193  // get to the first non-delim char
194  start = spec.find_first_not_of(delim, end);
195 
196  // read the end, no more to do
197  if (start == std::string::npos)
198  break;
199 
200  // find the end - next delim or end of string
201  end = spec.find_first_of(delim, start);
202 
203  // extract the fragment and remember it
204  output[i++] = atoi(spec.substr(start, (end == std::string::npos) ? std::string::npos : end - start).c_str());
205  }
206 
207  return i;
208 }
209 
210 static inline size_t SplitSpec(const std::string &spec, std::vector<float> &output)
211 {
212  static const std::string delim(",");
213 
214  size_t i = 0, start = 0, end = 0;
215  while (end != std::string::npos) {
216  // get to the first non-delim char
217  start = spec.find_first_not_of(delim, end);
218 
219  // read the end, no more to do
220  if (start == std::string::npos)
221  break;
222 
223  // find the end - next delim or end of string
224  end = spec.find_first_of(delim, start);
225 
226  // extract the fragment and remember it
227  output[i++] = atof(spec.substr(start, (end == std::string::npos) ? std::string::npos : end - start).c_str());
228  }
229 
230  return i;
231 }
232 
233 std::vector<std::string> SplitString(const std::string &source, const std::string &delim);
234 
235 // 'Numeric type' to string conversions.
236 std::string FloatToStr(float val);
237 std::string DoubleToStr(double val);
238 std::string AutoToStr(Sint32 val);
239 std::string AutoToStr(Sint64 val);
240 std::string AutoToStr(float val);
241 std::string AutoToStr(double val);
242 
243 void Vector3fToStr(const vector3f &val, char *out, size_t size);
244 void Vector3dToStr(const vector3d &val, char *out, size_t size);
245 void Matrix3x3fToStr(const matrix3x3f &val, char *out, size_t size);
246 void Matrix3x3dToStr(const matrix3x3d &val, char *out, size_t size);
247 void Matrix4x4fToStr(const matrix4x4f &val, char *out, size_t size);
248 void Matrix4x4dToStr(const matrix4x4d &val, char *out, size_t size);
249 
250 // String to 'Numeric type' conversions.
251 Sint64 StrToSInt64(const std::string &str);
252 Uint64 StrToUInt64(const std::string &str);
253 float StrToFloat(const std::string &str);
254 double StrToDouble(const std::string &str);
255 void StrToAuto(Sint32 *pVal, const std::string &str);
256 void StrToAuto(Sint64 *pVal, const std::string &str);
257 void StrToAuto(float *pVal, const std::string &str);
258 void StrToAuto(double *pVal, const std::string &str);
259 
260 void StrToVector3f(const char *str, vector3f &val);
261 void StrToVector3d(const char *str, vector3d &val);
262 void StrToMatrix3x3f(const char *str, matrix3x3f &val);
263 void StrToMatrix3x3d(const char *str, matrix3x3d &val);
264 void StrToMatrix4x4f(const char *str, matrix4x4f &val);
265 void StrToMatrix4x4d(const char *str, matrix4x4d &val);
266 
267 // Convert decimal coordinates to degree/minute/second format and return as string
268 std::string DecimalToDegMinSec(float dec);
269 
270 // add a few things that MSVC is missing
271 #if defined(_MSC_VER) && (_MSC_VER < 1800)
272 
273 // round & roundf. taken from http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/auxiliary/util/u_math.h
274 static inline double round(double x)
275 {
276  return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5);
277 }
278 
279 static inline float roundf(float x)
280 {
281  return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f);
282 }
283 #endif /* _MSC_VER < 1800 */
284 
285 static inline Uint32 ceil_pow2(Uint32 v)
286 {
287  v--;
288  v |= v >> 1;
289  v |= v >> 2;
290  v |= v >> 4;
291  v |= v >> 8;
292  v |= v >> 16;
293  v++;
294  return v;
295 }
296 
297 // An adaptor for automagic reverse range-for iteration of containers
298 // One might be able to specialize this for raw arrays, but that's beyond the
299 // point of its use-case.
300 // One might also point out that this is surely more work to code than simply
301 // writing an explicit iterator loop, to which I say: bah humbug!
302 template <typename T>
304  using iterator = typename T::reverse_iterator;
305  using const_iterator = typename T::const_reverse_iterator;
306 
307  using value_type = typename std::remove_reference<T>::type;
308 
310  ref(ref) {}
311 
312  iterator begin() { return ref.rbegin(); }
313  const_iterator begin() const { return ref.crbegin(); }
314 
315  iterator end() { return ref.rend(); }
316  const_iterator end() const { return ref.crend(); }
317 
318 private:
319  value_type &ref;
320 };
321 
322 // Use this function for automatic template parameter deduction
323 template <typename T>
325 
326 void hexdump(const unsigned char *buf, int bufsz);
327 
328 #endif /* _UTILS_H */
double val
Definition: PrecalcPath.cpp:40
Sint64 v
Definition: fixed.h:239
void LogOld(Severity sv, std::string message)
Definition: Log.cpp:167
void LogFatalOld(std::string message)
Definition: Log.cpp:175
Definition: utils.h:303
reverse_container_t(value_type &ref)
Definition: utils.h:309
iterator end()
Definition: utils.h:315
typename T::reverse_iterator iterator
Definition: utils.h:304
const_iterator end() const
Definition: utils.h:316
typename std::remove_reference< T >::type value_type
Definition: utils.h:307
const_iterator begin() const
Definition: utils.h:313
iterator begin()
Definition: utils.h:312
typename T::const_reverse_iterator const_iterator
Definition: utils.h:305
float StrToFloat(const std::string &str)
Definition: utils.cpp:448
bool compare_ci(const std::string_view s, const std::string_view t)
Definition: utils.h:136
std::string format_date_only(double time)
Definition: utils.cpp:83
std::vector< std::string > SplitString(const std::string &source, const std::string &delim)
Definition: utils.cpp:190
bool ends_with(const std::string_view s, const std::string_view t)
Definition: utils.h:104
void Vector3fToStr(const vector3f &val, char *out, size_t size)
Definition: utils.cpp:274
void Vector3dToStr(const vector3d &val, char *out, size_t size)
Definition: utils.cpp:292
void Matrix4x4fToStr(const matrix4x4f &val, char *out, size_t size)
Definition: utils.cpp:358
void Matrix3x3dToStr(const matrix3x3d &val, char *out, size_t size)
Definition: utils.cpp:334
void StrToAuto(Sint32 *pVal, const std::string &str)
Definition: utils.cpp:485
void Output(const char *message, Args... args)
Definition: utils.h:41
void StrToVector3f(const char *str, vector3f &val)
Definition: utils.cpp:505
void Matrix4x4dToStr(const matrix4x4d &val, char *out, size_t size)
Definition: utils.cpp:384
bool starts_with(const std::string_view s, const std::string_view t)
Definition: utils.h:97
void Matrix3x3fToStr(const matrix3x3f &val, char *out, size_t size)
Definition: utils.cpp:310
bool ends_with_ci(const std::string_view s, const std::string_view t)
Definition: utils.h:124
Uint64 StrToUInt64(const std::string &str)
Definition: utils.cpp:441
std::string_view read_line(std::string_view &s)
Definition: utils.h:148
reverse_container_t< T > reverse_container(T &ref)
Definition: utils.h:324
std::string format_money(double cents, bool showCents=true)
Definition: utils.cpp:17
std::string FloatToStr(float val)
Definition: utils.cpp:240
void DebugMsg(const char *message, Args... args)
Definition: utils.h:59
void StrToMatrix3x3f(const char *str, matrix3x3f &val)
Definition: utils.cpp:541
std::string string_join(std::vector< std::string > &v, std::string sep)
Definition: utils.cpp:94
bool starts_with_ci(const std::string_view s, const std::string_view t)
Definition: utils.h:112
void StrToMatrix4x4d(const char *str, matrix4x4d &val)
Definition: utils.cpp:601
void Warning(const char *message, Args... args)
Definition: utils.h:47
void hexdump(const unsigned char *buf, int bufsz)
Definition: utils.cpp:635
std::string format_date(double time)
Definition: utils.cpp:70
std::string format_duration(double seconds)
Definition: utils.cpp:107
void StrToMatrix4x4f(const char *str, matrix4x4f &val)
Definition: utils.cpp:581
std::string AutoToStr(Sint32 val)
Definition: utils.cpp:410
void StrToMatrix3x3d(const char *str, matrix3x3d &val)
Definition: utils.cpp:561
std::string_view strip_spaces(std::string_view &s)
Definition: utils.h:173
std::string format_distance(double dist, int precision=2)
Definition: utils.cpp:131
const char * pi_strcasestr(const char *haystack, const char *needle)
Definition: utils.cpp:159
double StrToDouble(const std::string &str)
Definition: utils.cpp:466
std::string DoubleToStr(double val)
Definition: utils.cpp:257
void Error(const char *message, Args... args)
Definition: utils.h:53
Sint64 StrToSInt64(const std::string &str)
Definition: utils.cpp:434
std::string DecimalToDegMinSec(float dec)
Definition: utils.cpp:625
void StrToVector3d(const char *str, vector3d &val)
Definition: utils.cpp:523