Libprimis
Imprimis' 3D destroyable world engine
Loading...
Searching...
No Matches
tools.h
Go to the documentation of this file.
1
9
10#ifndef TOOLS_H_
11#define TOOLS_H_
12
13typedef unsigned char uchar;
14typedef unsigned short ushort;
15typedef unsigned int uint;
16typedef unsigned long ulong;
17typedef signed long long int llong;
18typedef unsigned long long int ullong;
19
20#if defined(__GNUC__) || defined(_MSC_VER)
21 #define RESTRICT __restrict
22#else
23 #define RESTRICT
24#endif
25
26#ifdef max
27 #undef max
28#endif
29#ifdef min
30 #undef min
31#endif
32template<class T>
33inline T max(T a, T b)
34{
35 return a > b ? a : b;
36}
37template<class T>
38inline T max(T a, T b, T c)
39{
40 return max(max(a, b), c);
41}
42template<class T>
43inline T min(T a, T b)
44{
45 return a < b ? a : b;
46}
47template<class T>
48inline T min(T a, T b, T c)
49{
50 return min(min(a, b), c);
51}
52
53#ifdef __GNUC__
54 #define BITSCAN(mask) (__builtin_ffs(mask)-1)
55#else
56 #ifdef WIN32
57 #pragma intrinsic(_BitScanForward)
58 inline int BITSCAN(uint mask)
59 {
60 ulong i;
61 return _BitScanForward(&i, mask) ? i : -1;
62 }
63 #else
64 inline int BITSCAN(uint mask)
65 {
66 if(!mask) return -1;
67 int i = 1;
68 if(!(mask&0xFFFF)) { i += 16; mask >>= 16; }
69 if(!(mask&0xFF)) { i += 8; mask >>= 8; }
70 if(!(mask&0xF)) { i += 4; mask >>= 4; }
71 if(!(mask&3)) { i += 2; mask >>= 2; }
72 return i - (mask&1);
73 }
74 #endif
75#endif
76
77inline int randomint(int x)
78{
79 return rand()%(x);
80}
81inline float randomfloat(int x)
82{
83 return (float((rand()*float(x))/float(RAND_MAX)));
84}
85//1103515245+12345 are magic constants for LCG psuedorandom generator
86inline float detrnd(uint s, int x)
87{
88 return static_cast<int>(((s*1103515245+12345)>>16)%x);
89}
90
91constexpr double SQRT2 = 1.4142135623731;
92constexpr double SQRT3 = 1.73205080756888;
93
94#ifdef WIN32
95 #ifndef M_PI
96 constexpr double M_PI = 3.14159265358979323846;
97 #endif
98 #ifndef M_LN2
99 constexpr double M_LN2 = 0.693147180559945309417;
100 #endif
101
102 #ifndef __GNUC__
103 #pragma warning (3: 4189) // local variable is initialized but not referenced
104 #pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
105 #pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
106 #pragma warning (disable: 4355) // 'this' : used in base member initializer list
107 #pragma warning (disable: 4996) // 'strncpy' was declared deprecated
108 #endif
109
110 #define strcasecmp _stricmp
111 #define strncasecmp _strnicmp
112 #define PATHDIV '\\'
113
114#else
115 #define __cdecl
116 #define _vsnprintf vsnprintf
117 #define PATHDIV '/'
118#endif
119
120#define RAD static_cast<float>(180.0f / M_PI) //M_PI is a double
121
122
123#ifdef __GNUC__
124 #define PRINTFARGS(fmt, args) __attribute__((format(printf, fmt, args)))
125#else
126 #define PRINTFARGS(fmt, args)
127#endif
128
129// easy safe strings
130const int maxstrlen = 260;
131
132typedef char string[maxstrlen];
133
134inline void vformatstring(char *d, const char *fmt, va_list v, int len) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; }
135
136template<size_t N>
137inline void vformatstring(char (&d)[N], const char *fmt, va_list v) { vformatstring(d, fmt, v, N); }
138
139inline char *copystring(char *d, const char *s, size_t len)
140{
141 size_t slen = min(strlen(s), len-1);
142 std::memcpy(d, s, slen);
143 d[slen] = 0;
144 return d;
145}
146template<size_t N>
147inline char *copystring(char (&d)[N], const char *s) { return copystring(d, s, N); }
148
149inline char *concatstring(char *d, const char *s, size_t len) { size_t used = strlen(d); return used < len ? copystring(d+used, s, len-used) : d; }
150
151template<size_t N>
152inline char *concatstring(char (&d)[N], const char *s) { return concatstring(d, s, N); }
153
154inline void nformatstring(char *d, int len, const char *fmt, ...) PRINTFARGS(3, 4);
155inline void nformatstring(char *d, int len, const char *fmt, ...)
156{
157 va_list v;
158 va_start(v, fmt);
159 vformatstring(d, fmt, v, len);
160 va_end(v);
161}
162
163template<size_t N>
164inline void formatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
165
166template<size_t N>
167inline void formatstring(char (&d)[N], const char *fmt, ...)
168{
169 va_list v;
170 va_start(v, fmt);
171 vformatstring(d, fmt, v, static_cast<int>(N));
172 va_end(v);
173}
174
175template<size_t N>
176inline void concformatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
177
178template<size_t N>
179inline void concformatstring(char (&d)[N], const char *fmt, ...)
180{
181 va_list v;
182 va_start(v, fmt);
183 int len = strlen(d);
184 vformatstring(d + len, fmt, v, static_cast<int>(N) - len);
185 va_end(v);
186}
187
188extern char *tempformatstring(const char *fmt, ...) PRINTFARGS(1, 2);
189
190#define DEF_FORMAT_STRING(d,...) string d; formatstring(d, __VA_ARGS__)
191#define DEFV_FORMAT_STRING(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
192
193inline bool matchstring(std::string_view s, size_t len, std::string_view d)
194{
195 return len == d.size() && !std::memcmp(s.data(), d.data(), d.size());
196}
197
198inline char *newstring(size_t l)
199{
200 return new char[l+1];
201}
202inline char *newstring(const char *s, size_t l)
203{
204 return copystring(newstring(l), s, l+1);
205}
206inline char *newstring(const char *s)
207{
208 size_t l = strlen(s);
209 char *d = newstring(l);
210 std::memcpy(d, s, l+1);
211 return d;
212}
213
214inline char *newconcatstring(const char *s, const char *t)
215{
216 size_t slen = strlen(s),
217 tlen = strlen(t);
218 char *r = newstring(slen + tlen);
219 std::memcpy(r, s, slen);
220 std::memcpy(&r[slen], t, tlen);
221 r[slen+tlen] = '\0';
222 return r;
223}
224
225template <class T>
226struct databuf
227{
228 enum
229 {
230 OVERREAD = 1<<0,
231 OVERWROTE = 1<<1
232 };
233
234 T *buf;
235 int len, maxlen;
236 uchar flags;
237
238 databuf() : buf(nullptr), len(0), maxlen(0), flags(0) {}
239
240 template<class U>
241 databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
242
243 void reset()
244 {
245 len = 0;
246 flags = 0;
247 }
248
249 void reset(T *buf_, int maxlen_)
250 {
251 reset();
252 buf = buf_;
253 maxlen = maxlen_;
254 }
255
265 const T &get()
266 {
267 static const T overreadval = 0;
268 if(len<maxlen)
269 {
270 return buf[len++];
271 }
272 flags |= OVERREAD;
273 return overreadval;
274 }
275
289 databuf subbuf(int sz)
290 {
291 sz = std::clamp(sz, 0, maxlen-len);
292 len += sz;
293 return databuf(&buf[len-sz], sz);
294 }
295
306 T *pad(int numvals)
307 {
308 T *vals = &buf[len];
309 len += min(numvals, maxlen-len);
310 return vals;
311 }
312
320 void put(const T &val)
321 {
322 if(len<maxlen)
323 {
324 buf[len++] = val;
325 }
326 else
327 {
328 flags |= OVERWROTE;
329 }
330 }
331
332 void put(const T *vals, int numvals)
333 {
334 if(maxlen - len < numvals)
335 {
336 numvals = maxlen - len;
337 flags |= OVERWROTE;
338 }
339 std::memcpy(&buf[len], (const void *)vals, numvals*sizeof(T));
340 len += numvals;
341 }
342
343 int get(T *vals, int numvals)
344 {
345 if(maxlen - len < numvals)
346 {
347 numvals = maxlen - len;
348 flags |= OVERREAD;
349 }
350 std::memcpy(vals, (void *)&buf[len], numvals*sizeof(T));
351 len += numvals;
352 return numvals;
353 }
354
355 void offset(int n)
356 {
357 n = min(n, maxlen);
358 buf += n;
359 maxlen -= n;
360 len = max(len-n, 0);
361 }
362
371 T *getbuf() const { return buf; }
372
379 bool empty() const { return len==0; }
380
389 int length() const { return len; }
390
400 int remaining() const { return maxlen-len; }
401
412 bool overread() const { return (flags&OVERREAD)!=0; }
413
423 bool overwrote() const { return (flags&OVERWROTE)!=0; }
424
425 bool check(int n) { return remaining() >= n; }
426
427 void forceoverread()
428 {
429 len = maxlen;
430 flags |= OVERREAD;
431 }
432};
433
434typedef databuf<char> charbuf;
435typedef databuf<uchar> ucharbuf;
436
437inline uint memhash(const void *ptr, int len)
438{
439 const uchar *data = (const uchar *)ptr;
440 uint h = 5381;
441 for(int i = 0; i < static_cast<int>(len); ++i)
442 {
443 h = ((h<<5)+h)^data[i];
444 }
445 return h;
446}
447
448template<class T>
449inline T endianswap(T n) { union { T t; uint i; } conv; conv.t = n; conv.i = SDL_Swap32(conv.i); return conv.t; }
450
451template<>
452inline uint endianswap<uint>(uint n) { return SDL_Swap32(n); }
453
454template<>
455inline int endianswap<int>(int n) { return SDL_Swap32(n); }
456
457/* workaround for some C platforms that have these two functions as macros - not used anywhere */
458#ifdef getchar
459 #undef getchar
460#endif
461#ifdef putchar
462 #undef putchar
463#endif
464
465struct stream
466{
467#ifdef WIN32
468 #if defined(__GNUC__) && !defined(__MINGW32__)
469 typedef off64_t offset;
470 #else
471 typedef __int64 offset;
472 #endif
473 #else
474 typedef off_t offset;
475#endif
476 //see file/gz/zipstream children for more interesting forms
477 virtual ~stream() {}
478 virtual void close() = 0;
479 virtual bool end() = 0;
480 virtual offset tell() { return -1; }
481 virtual offset rawtell() { return tell(); }
482 virtual bool seek(offset, int) { return false; }
483 virtual offset size();
484 virtual offset rawsize() { return size(); }
485 virtual size_t read(void *, size_t) { return 0; }
486 virtual size_t write(const void *, size_t) { return 0; }
487 virtual bool flush() { return true; }
488 virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
489 virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
490 virtual bool getline(char *str, size_t len);
491 virtual bool putstring(const char *str) { size_t len = strlen(str); return write(str, len) == len; }
492 virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
493 virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3);
494 virtual uint getcrc() { return 0; }
495
496 template<class T>
497 size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); }
498
499 template<class T>
500 bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
501
502 template<class T>
503 size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); }
504
505 template<class T>
506 T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
507
508 template<class T>
509 bool putbig(T n) { return put<T>(endianswap(n)); }
510
511 SDL_RWops *rwops();
512};
513
514extern string homedir;
515
516extern char *path(char *s);
517extern std::string path(std::string s);
518extern char *copypath(const char *s);
519extern const char *sethomedir(const char *dir);
520extern const char *findfile(const char *filename, const char *mode);
521
529extern void initzipcmds();
530
531extern stream *openrawfile(const char *filename, const char *mode);
532extern stream *openzipfile(const char *filename, const char *mode);
533extern stream *openfile(const char *filename, const char *mode);
534extern stream *opengzfile(const char *filename, const char *mode, stream *file = nullptr, int level = Z_BEST_COMPRESSION);
535
536template<class T>
537inline void putint_(T &p, int n)
538{
539 if(n<128 && n>-127)
540 {
541 p.put(n);
542 }
543 else if(n<0x8000 && n>=-0x8000)
544 {
545 p.put(0x80);
546 p.put(n);
547 p.put(n>>8);
548 }
549 else
550 {
551 p.put(0x81);
552 p.put(n);
553 p.put(n>>8);
554 p.put(n>>16);
555 p.put(n>>24);
556 }
557}
558
559template<class T>
560inline void putuint_(T &p, int n)
561{
562 if(n < 0 || n >= (1<<21))
563 {
564 p.put(0x80 | (n & 0x7F));
565 p.put(0x80 | ((n >> 7) & 0x7F));
566 p.put(0x80 | ((n >> 14) & 0x7F));
567 p.put(n >> 21);
568 }
569 else if(n < (1<<7))
570 {
571 p.put(n);
572 }
573 else if(n < (1<<14))
574 {
575 p.put(0x80 | (n & 0x7F));
576 p.put(n >> 7);
577 }
578 else
579 {
580 p.put(0x80 | (n & 0x7F));
581 p.put(0x80 | ((n >> 7) & 0x7F));
582 p.put(n >> 14);
583 }
584}
585
586extern void putint(std::vector<uchar> &p, int n);
587
588template<typename T>
589inline void vectorput(std::vector<uint8_t>& buf, const T& data)
590{
591 const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&data);
592 buf.insert(buf.end(), data_ptr, data_ptr + sizeof(T));
593}
594
595inline void vectorput(std::vector<uint8_t>& buf, const uint8_t* data, size_t size)
596{
597 buf.insert(buf.end(), data, data + size);
598}
599
600template<class T>
601inline void sendstring_(const char *t, T &p)
602{
603 while(*t)
604 {
605 putint(p, *t++);
606 }
607 putint(p, 0);
608}
609
610template<class T>
611inline void putfloat_(T &p, float f)
612{
613 p.put((uchar *)&f, sizeof(float));
614}
615
616extern void putint(ucharbuf &p, int n);
617extern int getint(ucharbuf &p);
618extern void putuint(ucharbuf &p, int n);
619extern int getuint(ucharbuf &p);
620extern void putfloat(ucharbuf &p, float f);
621extern float getfloat(ucharbuf &p);
622extern void sendstring(const char *t, ucharbuf &p);
623extern void getstring(char *t, ucharbuf &p, size_t len);
624
625template<size_t N>
626inline void getstring(char (&t)[N], ucharbuf &p) { getstring(t, p, N); }
627
628extern void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len);
629
630template<size_t N>
631inline void filtertext(char (&dst)[N], const char *src, bool whitespace = true, bool forcespace = false) { filtertext(dst, src, whitespace, forcespace, N-1); }
632
633#endif /* TOOLS_H_ */
Definition tools.h:227
const T & get()
Adds an existing value in the underlying buffer to the databuf.
Definition tools.h:265
int length() const
Returns the number of allocated entries in the databuf.
Definition tools.h:389
void put(const T &val)
Adds an entry to the databuf if space is available.
Definition tools.h:320
databuf subbuf(int sz)
Returns a databuf<T> object containing the first n entries.
Definition tools.h:289
bool overread() const
Returns whether the databuf has been accessed with too large of an index.
Definition tools.h:412
T * pad(int numvals)
Adds N empty elements to the end of the array and returns a pointer.
Definition tools.h:306
int remaining() const
Returns the number of values remaining before the databuf overflows.
Definition tools.h:400
bool empty() const
Returns whether any entries have been assigned to the array.
Definition tools.h:379
T * getbuf() const
Returns a pointer to the internal data array.
Definition tools.h:371
bool overwrote() const
Returns whether the databuf has had invalid writes to it.
Definition tools.h:423
Definition tools.h:466
void initzipcmds()
Initializes zip Cubescript commands.