Pioneer
Loading...
Searching...
No Matches
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
40template <typename... Args>
41inline void Output(const char *message, Args... args)
42{
43 Log::LogOld(Log::Severity::Info, fmt::sprintf(message, args...));
44}
45
46template <typename... Args>
47inline void Warning(const char *message, Args... args)
48{
49 Log::LogOld(Log::Severity::Warning, fmt::sprintf(message, args...));
50}
51
52template <typename... Args>
53[[noreturn]] inline void Error(const char *message, Args... args)
54{
55 Log::LogFatalOld(fmt::sprintf(message, args...));
56}
57
58template <typename... Args>
59inline void DebugMsg(const char *message, Args... args)
60{
61 Log::LogOld(Log::Severity::Debug, fmt::sprintf(message, args...));
62}
63
64std::string string_join(std::vector<std::string> &v, std::string sep);
65std::string format_date(double time);
66std::string format_date_only(double time);
67std::string format_distance(double dist, int precision = 2);
68std::string format_money(double cents, bool showCents = true);
69std::string format_duration(double seconds);
70
71static 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
77static 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
95const char *pi_strcasestr(const char *haystack, const char *needle);
96
97inline 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
104inline 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
112inline 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
124inline 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
136inline 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
148inline 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
173inline 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
187static 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
210static 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
233std::vector<std::string> SplitString(const std::string &source, const std::string &delim);
234
235// 'Numeric type' to string conversions.
236std::string FloatToStr(float val);
237std::string DoubleToStr(double val);
238std::string AutoToStr(Sint32 val);
239std::string AutoToStr(Sint64 val);
240std::string AutoToStr(float val);
241std::string AutoToStr(double val);
242
243void Vector3fToStr(const vector3f &val, char *out, size_t size);
244void Vector3dToStr(const vector3d &val, char *out, size_t size);
245void Matrix3x3fToStr(const matrix3x3f &val, char *out, size_t size);
246void Matrix3x3dToStr(const matrix3x3d &val, char *out, size_t size);
247void Matrix4x4fToStr(const matrix4x4f &val, char *out, size_t size);
248void Matrix4x4dToStr(const matrix4x4d &val, char *out, size_t size);
249
250// String to 'Numeric type' conversions.
251Sint64 StrToSInt64(const std::string &str);
252Uint64 StrToUInt64(const std::string &str);
253float StrToFloat(const std::string &str);
254double StrToDouble(const std::string &str);
255void StrToAuto(Sint32 *pVal, const std::string &str);
256void StrToAuto(Sint64 *pVal, const std::string &str);
257void StrToAuto(float *pVal, const std::string &str);
258void StrToAuto(double *pVal, const std::string &str);
259
260void StrToVector3f(const char *str, vector3f &val);
261void StrToVector3d(const char *str, vector3d &val);
262void StrToMatrix3x3f(const char *str, matrix3x3f &val);
263void StrToMatrix3x3d(const char *str, matrix3x3d &val);
264void StrToMatrix4x4f(const char *str, matrix4x4f &val);
265void StrToMatrix4x4d(const char *str, matrix4x4d &val);
266
267// Convert decimal coordinates to degree/minute/second format and return as string
268std::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
274static inline double round(double x)
275{
276 return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5);
277}
278
279static 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
285static 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!
302template <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
318private:
319 value_type &ref;
320};
321
322// Use this function for automatic template parameter deduction
323template <typename T>
325
326void 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
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
std::vector< std::string > SplitString(const std::string &source, const std::string &delim)
Definition utils.cpp:190
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
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
reverse_container_t< T > reverse_container(T &ref)
Definition utils.h:324
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