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 char *newstring(size_t l)
194{
195 return new char[l+1];
196}
197
198inline char *newstring(const char *s, size_t l)
199{
200 return copystring(newstring(l), s, l+1);
201}
202
203inline char *newstring(const char *s)
204{
205 size_t l = strlen(s);
206 char *d = newstring(l);
207 std::memcpy(d, s, l+1);
208 return d;
209}
210
211inline char *newconcatstring(const char *s, const char *t)
212{
213 size_t slen = strlen(s),
214 tlen = strlen(t);
215 char *r = newstring(slen + tlen);
216 std::memcpy(r, s, slen);
217 std::memcpy(&r[slen], t, tlen);
218 r[slen+tlen] = '\0';
219 return r;
220}
221
222template <class T>
223struct databuf
224{
225 enum
226 {
227 OVERREAD = 1<<0,
228 OVERWROTE = 1<<1
229 };
230
231 T *buf;
232 int len, maxlen;
233 uchar flags;
234
235 databuf() : buf(nullptr), len(0), maxlen(0), flags(0) {}
236
237 template<class U>
238 databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen(static_cast<int>(maxlen)), flags(0) {}
239
240 void reset()
241 {
242 len = 0;
243 flags = 0;
244 }
245
246 void reset(T *buf_, int maxlen_)
247 {
248 reset();
249 buf = buf_;
250 maxlen = maxlen_;
251 }
252
262 const T &get()
263 {
264 static const T overreadval = 0;
265 if(len<maxlen)
266 {
267 return buf[len++];
268 }
269 flags |= OVERREAD;
270 return overreadval;
271 }
272
286 databuf subbuf(int sz)
287 {
288 sz = std::clamp(sz, 0, maxlen-len);
289 len += sz;
290 return databuf(&buf[len-sz], sz);
291 }
292
303 T *pad(int numvals)
304 {
305 T *vals = &buf[len];
306 len += min(numvals, maxlen-len);
307 return vals;
308 }
309
317 void put(const T &val)
318 {
319 if(len<maxlen)
320 {
321 buf[len++] = val;
322 }
323 else
324 {
325 flags |= OVERWROTE;
326 }
327 }
328
329 void put(const T *vals, int numvals)
330 {
331 if(maxlen - len < numvals)
332 {
333 numvals = maxlen - len;
334 flags |= OVERWROTE;
335 }
336 std::memcpy(&buf[len], static_cast<const void *>(vals), numvals*sizeof(T));
337 len += numvals;
338 }
339
340 int get(T *vals, int numvals)
341 {
342 if(maxlen - len < numvals)
343 {
344 numvals = maxlen - len;
345 flags |= OVERREAD;
346 }
347 std::memcpy(vals, static_cast<void *>(&buf[len]), numvals*sizeof(T));
348 len += numvals;
349 return numvals;
350 }
351
352 void offset(int n)
353 {
354 n = min(n, maxlen);
355 buf += n;
356 maxlen -= n;
357 len = max(len-n, 0);
358 }
359
368 T *getbuf() const { return buf; }
369
376 bool empty() const { return len==0; }
377
386 int length() const { return len; }
387
397 int remaining() const { return maxlen-len; }
398
409 bool overread() const { return (flags&OVERREAD)!=0; }
410
420 bool overwrote() const { return (flags&OVERWROTE)!=0; }
421
422 bool check(int n) { return remaining() >= n; }
423
424 void forceoverread()
425 {
426 len = maxlen;
427 flags |= OVERREAD;
428 }
429};
430
431typedef databuf<char> charbuf;
432typedef databuf<uchar> ucharbuf;
433
434inline uint memhash(const void *ptr, int len)
435{
436 const uchar *data = static_cast<const uchar *>(ptr);
437 uint h = 5381;
438 for(int i = 0; i < static_cast<int>(len); ++i)
439 {
440 h = ((h<<5)+h)^data[i];
441 }
442 return h;
443}
444
445template<class T>
446inline T endianswap(T n) { union { T t; uint i; } conv; conv.t = n; conv.i = SDL_Swap32(conv.i); return conv.t; }
447
448template<>
449inline uint endianswap<uint>(uint n) { return SDL_Swap32(n); }
450
451template<>
452inline int endianswap<int>(int n) { return SDL_Swap32(n); }
453
454/* workaround for some C platforms that have these two functions as macros - not used anywhere */
455#ifdef getchar
456 #undef getchar
457#endif
458#ifdef putchar
459 #undef putchar
460#endif
461
462struct stream
463{
464#ifdef WIN32
465 #if defined(__GNUC__) && !defined(__MINGW32__)
466 typedef off64_t offset;
467 #else
468 typedef __int64 offset;
469 #endif
470 #else
471 typedef off_t offset;
472#endif
473 //see file/gz/zipstream children for more interesting forms
474 virtual ~stream() {}
475 virtual void close() = 0;
476 virtual bool end() = 0;
477 virtual offset tell() const { return -1; }
478 virtual offset rawtell() const { return tell(); }
479 virtual bool seek(offset, int) { return false; }
480 virtual offset size();
481 virtual offset rawsize() { return size(); }
482 virtual size_t read(void *, size_t) { return 0; }
483 virtual size_t write(const void *, size_t) { return 0; }
484 virtual bool flush() { return true; }
485 virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
486 virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
487 virtual bool getline(char *str, size_t len);
488 virtual bool putstring(const char *str) { size_t len = strlen(str); return write(str, len) == len; }
489 virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
490 virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3);
491 virtual uint getcrc() { return 0; }
492
493 template<class T>
494 size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); }
495
496 template<class T>
497 bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
498
499 template<class T>
500 size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); }
501
502 template<class T>
503 T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
504
505 template<class T>
506 bool putbig(T n) { return put<T>(endianswap(n)); }
507
508 SDL_RWops *rwops();
509};
510
511extern std::string homedir;
512
513extern char *path(char *s);
514extern std::string path(std::string s);
515extern char *copypath(const char *s);
516extern const char *sethomedir(const char *dir);
517extern const char *findfile(const char *filename, const char *mode);
518
526extern void initzipcmds();
527
528extern stream *openrawfile(const char *filename, const char *mode);
529extern stream *openzipfile(const char *filename, const char *mode);
530extern stream *openfile(const char *filename, const char *mode);
531extern stream *opengzfile(const char *filename, const char *mode, stream *file = nullptr, int level = Z_BEST_COMPRESSION);
532
533template<class T>
534inline void putint_(T &p, int n)
535{
536 if(n<128 && n>-127)
537 {
538 p.put(n);
539 }
540 else if(n<0x8000 && n>=-0x8000)
541 {
542 p.put(0x80);
543 p.put(n);
544 p.put(n>>8);
545 }
546 else
547 {
548 p.put(0x81);
549 p.put(n);
550 p.put(n>>8);
551 p.put(n>>16);
552 p.put(n>>24);
553 }
554}
555
556template<class T>
557inline void putuint_(T &p, int n)
558{
559 if(n < 0 || n >= (1<<21))
560 {
561 p.put(0x80 | (n & 0x7F));
562 p.put(0x80 | ((n >> 7) & 0x7F));
563 p.put(0x80 | ((n >> 14) & 0x7F));
564 p.put(n >> 21);
565 }
566 else if(n < (1<<7))
567 {
568 p.put(n);
569 }
570 else if(n < (1<<14))
571 {
572 p.put(0x80 | (n & 0x7F));
573 p.put(n >> 7);
574 }
575 else
576 {
577 p.put(0x80 | (n & 0x7F));
578 p.put(0x80 | ((n >> 7) & 0x7F));
579 p.put(n >> 14);
580 }
581}
582
583extern void putint(std::vector<uchar> &p, int n);
584
585template<typename T>
586inline void vectorput(std::vector<uint8_t>& buf, const T& data)
587{
588 const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&data);
589 buf.insert(buf.end(), data_ptr, data_ptr + sizeof(T));
590}
591
592inline void vectorput(std::vector<uint8_t>& buf, const uint8_t* data, size_t size)
593{
594 buf.insert(buf.end(), data, data + size);
595}
596
597template<class T>
598inline void sendstring_(const char *t, T &p)
599{
600 while(*t)
601 {
602 putint(p, *t++);
603 }
604 putint(p, 0);
605}
606
607template<class T>
608inline void putfloat_(T &p, float f)
609{
610 p.put(reinterpret_cast<uchar *>(&f), sizeof(float));
611}
612
613extern void putint(ucharbuf &p, int n);
614extern int getint(ucharbuf &p);
615extern void putuint(ucharbuf &p, int n);
616extern int getuint(ucharbuf &p);
617extern void putfloat(ucharbuf &p, float f);
618extern float getfloat(ucharbuf &p);
619extern void sendstring(const char *t, ucharbuf &p);
620extern void getstring(char *t, ucharbuf &p, size_t len);
621
622template<size_t N>
623inline void getstring(char (&t)[N], ucharbuf &p) { getstring(t, p, N); }
624
625extern void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len);
626
627template<size_t N>
628inline void filtertext(char (&dst)[N], const char *src, bool whitespace = true, bool forcespace = false) { filtertext(dst, src, whitespace, forcespace, N-1); }
629
630#endif /* TOOLS_H_ */
Definition tools.h:224
const T & get()
Adds an existing value in the underlying buffer to the databuf.
Definition tools.h:262
int length() const
Returns the number of allocated entries in the databuf.
Definition tools.h:386
void put(const T &val)
Adds an entry to the databuf if space is available.
Definition tools.h:317
databuf subbuf(int sz)
Returns a databuf<T> object containing the first n entries.
Definition tools.h:286
bool overread() const
Returns whether the databuf has been accessed with too large of an index.
Definition tools.h:409
T * pad(int numvals)
Adds N empty elements to the end of the array and returns a pointer.
Definition tools.h:303
int remaining() const
Returns the number of values remaining before the databuf overflows.
Definition tools.h:397
bool empty() const
Returns whether any entries have been assigned to the array.
Definition tools.h:376
T * getbuf() const
Returns a pointer to the internal data array.
Definition tools.h:368
bool overwrote() const
Returns whether the databuf has had invalid writes to it.
Definition tools.h:420
Definition tools.h:463
void initzipcmds()
Initializes zip Cubescript commands.