1 // generic useful stuff for any C++ program
2 
3 #ifndef _TOOLS_H
4 #define _TOOLS_H
5 
6 #ifdef NULL
7 #undef NULL
8 #endif
9 #define NULL 0
10 
11 typedef unsigned char uchar;
12 typedef unsigned short ushort;
13 typedef unsigned int uint;
14 
15 #ifdef _DEBUG
16 #ifdef __GNUC__
17 #define ASSERT(c) if(!(c)) { asm("int $3"); }
18 #else
19 #define ASSERT(c) if(!(c)) { __asm int 3 }
20 #endif
21 #else
22 #define ASSERT(c) if(c) {}
23 #endif
24 
25 #ifdef swap
26 #undef swap
27 #endif
28 template<class T>
swap(T & a,T & b)29 static inline void swap(T &a, T &b)
30 {
31     T t = a;
32     a = b;
33     b = t;
34 }
35 #ifdef max
36 #undef max
37 #endif
38 #ifdef min
39 #undef min
40 #endif
41 template<class T>
max(T a,T b)42 static inline T max(T a, T b)
43 {
44     return a > b ? a : b;
45 }
46 template<class T>
min(T a,T b)47 static inline T min(T a, T b)
48 {
49     return a < b ? a : b;
50 }
51 
52 #define clamp(a,b,c) (max(b, min(a, c)))
53 #define rnd(x) ((int)(randomMT()&0xFFFFFF)%(x))
54 #define rndscale(x) (float((randomMT()&0xFFFFFF)*double(x)/double(0xFFFFFF)))
55 #define detrnd(s, x) ((int)(((((uint)(s))*1103515245+12345)>>16)%(x)))
56 #define isnumeric(c) (isdigit(c) || c == '+' || c == '-')
57 
58 #define loop(v,m) for(int v = 0; v<int(m); v++)
59 #define loopi(m) loop(i,m)
60 #define loopj(m) loop(j,m)
61 #define loopk(m) loop(k,m)
62 #define loopl(m) loop(l,m)
63 #define loopirev(v) for(int i = v-1; i>=0; i--)
64 
65 
66 #define DELETEP(p) if(p) { delete   p; p = 0; }
67 #define DELETEA(p) if(p) { delete[] p; p = 0; }
68 
69 #define PI  (3.1415927f)
70 #define PI2 (2*PI)
71 #define SQRT2 (1.4142136f)
72 #define SQRT3 (1.7320508f)
73 #define RAD (PI / 180.0f)
74 
75 #ifdef WIN32
76 #ifdef M_PI
77 #undef M_PI
78 #endif
79 #define M_PI 3.14159265
80 
81 #ifndef __GNUC__
82 #pragma warning (3: 4189)       // local variable is initialized but not referenced
83 #pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
84 #pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
85 #pragma warning (disable: 4355) // 'this' : used in base member initializer list
86 #pragma warning (disable: 4996) // 'strncpy' was declared deprecated
87 #pragma warning (disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
88 #endif
89 
90 #define strcasecmp _stricmp
91 #define PATHDIV '\\'
92 #else
93 #define __cdecl
94 #define _vsnprintf vsnprintf
95 #define PATHDIV '/'
96 #endif
97 
98 // easy safe strings
99 
100 #define MAXSTRLEN 512 // must be at least 512 bytes to comply with rfc1459
101 typedef char string[MAXSTRLEN];
102 #define mkstring(d) string d; d[0] = 0;
103 
104 inline void vformatstring(char *d, const char *fmt, va_list v, int len = MAXSTRLEN) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; }
105 inline char *copystring(char *d, const char *s, size_t len = MAXSTRLEN) { strncpy(d, s, len); d[len-1] = 0; return d; }
concatstring(char * d,const char * s)106 inline char *concatstring(char *d, const char *s) { size_t len = strlen(d); return copystring(d+len, s, MAXSTRLEN-len); }
107 
108 struct stringformatter
109 {
110     char *buf;
stringformatterstringformatter111     stringformatter(char *buf): buf((char *)buf) {}
operatorstringformatter112     void operator()(const char *fmt, ...)
113     {
114         va_list v;
115         va_start(v, fmt);
116         vformatstring(buf, fmt, v);
117         va_end(v);
118     }
119 };
120 
121 #define formatstring(d) stringformatter((char *)d)
122 #define defformatstring(d) string d; formatstring(d)
123 #define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
124 
125 #define loopv(v)    for(int i = 0; i<(v).length(); i++)
126 #define loopvj(v)   for(int j = 0; j<(v).length(); j++)
127 #define loopvk(v)   for(int k = 0; k<(v).length(); k++)
128 #define loopvrev(v) for(int i = (v).length()-1; i>=0; i--)
129 
130 template <class T>
131 struct databuf
132 {
133     enum
134     {
135         OVERREAD  = 1<<0,
136         OVERWROTE = 1<<1
137     };
138 
139     T *buf;
140     int len, maxlen;
141     uchar flags;
142 
databufdatabuf143     databuf() : buf(NULL), len(0), maxlen(0), flags(0) {}
144 
145     template<class U>
databufdatabuf146     databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
147 
getdatabuf148     const T &get()
149     {
150         static T overreadval;
151         if(len<maxlen) return buf[len++];
152         flags |= OVERREAD;
153         return overreadval;
154     }
155 
subbufdatabuf156     databuf subbuf(int sz)
157     {
158         sz = min(sz, maxlen-len);
159         len += sz;
160         return databuf(&buf[len-sz], sz);
161     }
162 
putdatabuf163     void put(const T &val)
164     {
165         if(len<maxlen) buf[len++] = val;
166         else flags |= OVERWROTE;
167     }
168 
putdatabuf169     void put(const T *vals, int numvals)
170     {
171         if(maxlen-len<numvals) flags |= OVERWROTE;
172         memcpy(&buf[len], vals, min(maxlen-len, numvals)*sizeof(T));
173         len += min(maxlen-len, numvals);
174     }
175 
getdatabuf176     int get(T *vals, int numvals)
177     {
178         int read = min(maxlen-len, numvals);
179         if(read<numvals) flags |= OVERREAD;
180         memcpy(vals, &buf[len], read*sizeof(T));
181         len += read;
182         return read;
183     }
184 
lengthdatabuf185     int length() const { return len; }
remainingdatabuf186     int remaining() const { return maxlen-len; }
overreaddatabuf187     bool overread() const { return (flags&OVERREAD)!=0; }
overwrotedatabuf188     bool overwrote() const { return (flags&OVERWROTE)!=0; }
189 
forceoverreaddatabuf190     void forceoverread()
191     {
192         len = maxlen;
193         flags |= OVERREAD;
194     }
195 };
196 
197 typedef databuf<char> charbuf;
198 typedef databuf<uchar> ucharbuf;
199 
200 struct packetbuf : ucharbuf
201 {
202     ENetPacket *packet;
203     int growth;
204 
packetbufpacketbuf205     packetbuf(ENetPacket *packet) : ucharbuf(packet->data, packet->dataLength), packet(packet), growth(0) {}
growthpacketbuf206     packetbuf(int growth, int pflags = 0) : growth(growth)
207     {
208         packet = enet_packet_create(NULL, growth, pflags);
209         buf = (uchar *)packet->data;
210         maxlen = packet->dataLength;
211     }
~packetbufpacketbuf212     ~packetbuf() { cleanup(); }
213 
reliablepacketbuf214     void reliable() { packet->flags |= ENET_PACKET_FLAG_RELIABLE; }
215 
resizepacketbuf216     void resize(int n)
217     {
218         enet_packet_resize(packet, n);
219         buf = (uchar *)packet->data;
220         maxlen = packet->dataLength;
221     }
222 
checkspacepacketbuf223     void checkspace(int n)
224     {
225         if(len + n > maxlen && packet && growth > 0) resize(max(len + n, maxlen + growth));
226     }
227 
subbufpacketbuf228     ucharbuf subbuf(int sz)
229     {
230         checkspace(sz);
231         return ucharbuf::subbuf(sz);
232     }
233 
putpacketbuf234     void put(const uchar &val)
235     {
236         checkspace(1);
237         ucharbuf::put(val);
238     }
239 
putpacketbuf240     void put(const uchar *vals, int numvals)
241     {
242         checkspace(numvals);
243         ucharbuf::put(vals, numvals);
244     }
245 
finalizepacketbuf246     ENetPacket *finalize()
247     {
248         resize(len);
249         return packet;
250     }
251 
cleanuppacketbuf252     void cleanup()
253     {
254         if(growth > 0 && packet && !packet->referenceCount) { enet_packet_destroy(packet); packet = NULL; buf = NULL; len = maxlen = 0; }
255     }
256 };
257 
258 template<class T>
heapscore(const T & n)259 static inline float heapscore(const T &n) { return n; }
260 
261 template<class T, class U>
quicksort(T * buf,int n,int (__cdecl * func)(U *,U *))262 static inline void quicksort(T *buf, int n, int (__cdecl *func)(U *, U *))
263 {
264     qsort(buf, n, sizeof(T), (int (__cdecl *)(const void *,const void *))func);
265 }
266 
267 template <class T> struct vector
268 {
269     static const int MINSIZE = 8;
270 
271     T *buf;
272     int alen, ulen;
273 
vectorvector274     vector() : buf(NULL), alen(0), ulen(0)
275     {
276     }
277 
vectorvector278     vector(const vector &v) : buf(NULL), alen(0), ulen(0)
279     {
280         *this = v;
281     }
282 
~vectorvector283     ~vector() { setsize(0); if(buf) delete[] (uchar *)buf; }
284 
285     vector<T> &operator=(const vector<T> &v)
286     {
287         setsize(0);
288         if(v.length() > alen) vrealloc(v.length());
289         loopv(v) add(v[i]);
290         return *this;
291     }
292 
addvector293     T &add(const T &x)
294     {
295         if(ulen==alen) vrealloc(ulen+1);
296         new (&buf[ulen]) T(x);
297         return buf[ulen++];
298     }
299 
addvector300     T &add()
301     {
302         if(ulen==alen) vrealloc(ulen+1);
303         new (&buf[ulen]) T;
304         return buf[ulen++];
305     }
306 
dupvector307     T &dup()
308     {
309         if(ulen==alen) vrealloc(ulen+1);
310         new (&buf[ulen]) T(buf[ulen-1]);
311         return buf[ulen++];
312     }
313 
movevector314     void move(vector<T> &v)
315     {
316         if(!ulen)
317         {
318             swap(buf, v.buf);
319             swap(ulen, v.ulen);
320             swap(alen, v.alen);
321         }
322         else
323         {
324             vrealloc(ulen+v.ulen);
325             if(v.ulen) memcpy(&buf[ulen], v.buf, v.ulen*sizeof(T));
326             ulen += v.ulen;
327             v.ulen = 0;
328         }
329     }
330 
inrangevector331     bool inrange(size_t i) const { return i<size_t(ulen); }
inrangevector332     bool inrange(int i) const { return i>=0 && i<ulen; }
333 
popvector334     T &pop() { return buf[--ulen]; }
lastvector335     T &last() { return buf[ulen-1]; }
dropvector336     void drop() { ulen--; buf[ulen].~T(); }
emptyvector337     bool empty() const { return ulen==0; }
338 
capacityvector339     int capacity() const { return alen; }
lengthvector340     int length() const { return ulen; }
341     T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; }
342     const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; }
343 
setsizevector344     void setsize(int i)         { ASSERT(i<=ulen); while(ulen>i) drop(); }
setsizenodeletevector345     void setsizenodelete(int i) { ASSERT(i<=ulen); ulen = i; }
346 
deletecontentspvector347     void deletecontentsp() { while(!empty()) delete   pop(); }
deletecontentsavector348     void deletecontentsa() { while(!empty()) delete[] pop(); }
349 
getbufvector350     T *getbuf() { return buf; }
getbufvector351     const T *getbuf() const { return buf; }
inbufvector352     bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; }
353 
354     template<class ST>
355     void sort(int (__cdecl *cf)(ST *, ST *), int i = 0, int n = -1)
356     {
357         quicksort(&buf[i], n < 0 ? ulen : n, cf);
358     }
359 
vreallocvector360     void vrealloc(int sz)
361     {
362         int olen = alen;
363         if(!alen) alen = max(MINSIZE, sz);
364         else while(alen < sz) alen *= 2;
365         if(alen <= olen) return;
366         uchar *newbuf = new uchar[alen*sizeof(T)];
367         if(olen > 0)
368         {
369             memcpy(newbuf, buf, olen*sizeof(T));
370             delete[] (uchar *)buf;
371         }
372         buf = (T *)newbuf;
373     }
374 
reservevector375     databuf<T> reserve(int sz)
376     {
377         if(ulen+sz > alen) vrealloc(ulen+sz);
378         return databuf<T>(&buf[ulen], sz);
379     }
380 
advancevector381     void advance(int sz)
382     {
383         ulen += sz;
384     }
385 
addbufvector386     void addbuf(const databuf<T> &p)
387     {
388         advance(p.length());
389     }
390 
putvector391 	void put(const T &v) { add(v); }
392 
putvector393     void put(const T *v, int n)
394     {
395         databuf<T> buf = reserve(n);
396         buf.put(v, n);
397         addbuf(buf);
398     }
399 
removevector400     void remove(int i, int n)
401     {
402         for(int p = i+n; p<ulen; p++) buf[p-n] = buf[p];
403         ulen -= n;
404     }
405 
removevector406     T remove(int i)
407     {
408         T e = buf[i];
409         for(int p = i+1; p<ulen; p++) buf[p-1] = buf[p];
410         ulen--;
411         return e;
412     }
413 
removeunorderedvector414     T removeunordered(int i)
415     {
416         T e = buf[i];
417         ulen--;
418         if(ulen>0) buf[i] = buf[ulen];
419         return e;
420     }
421 
422     template<class U>
findvector423     int find(const U &o)
424     {
425         loopi(ulen) if(buf[i]==o) return i;
426         return -1;
427     }
428 
removeobjvector429     void removeobj(const T &o)
430     {
431         loopi(ulen) if(buf[i]==o) remove(i--);
432     }
433 
replacewithlastvector434     void replacewithlast(const T &o)
435     {
436         if(!ulen) return;
437         loopi(ulen-1) if(buf[i]==o)
438         {
439             buf[i] = buf[ulen-1];
440         }
441         ulen--;
442     }
443 
insertvector444     T &insert(int i, const T &e)
445     {
446         add(T());
447         for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1];
448         buf[i] = e;
449         return buf[i];
450     }
451 
insertvector452     T *insert(int i, const T *e, int n)
453     {
454         if(ulen+n>alen) vrealloc(ulen+n);
455         loopj(n) add(T());
456         for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n];
457         loopj(n) buf[i+j] = e[j];
458         return &buf[i];
459     }
460 
reversevector461     void reverse()
462     {
463         loopi(ulen/2) swap(buf[i], buf[ulen-1-i]);
464     }
465 
heapparentvector466     static int heapparent(int i) { return (i - 1) >> 1; }
heapchildvector467     static int heapchild(int i) { return (i << 1) + 1; }
468 
buildheapvector469     void buildheap()
470     {
471         for(int i = ulen/2; i >= 0; i--) downheap(i);
472     }
473 
upheapvector474     int upheap(int i)
475     {
476         float score = heapscore(buf[i]);
477         while(i > 0)
478         {
479             int pi = heapparent(i);
480             if(score >= heapscore(buf[pi])) break;
481             swap(buf[i], buf[pi]);
482             i = pi;
483         }
484         return i;
485     }
486 
addheapvector487     T &addheap(const T &x)
488     {
489         add(x);
490         return buf[upheap(ulen-1)];
491     }
492 
downheapvector493     int downheap(int i)
494     {
495         float score = heapscore(buf[i]);
496         for(;;)
497         {
498             int ci = heapchild(i);
499             if(ci >= ulen) break;
500             float cscore = heapscore(buf[ci]);
501             if(score > cscore)
502             {
503                if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; }
504                else { swap(buf[ci], buf[i]); i = ci; }
505             }
506             else if(ci+1 < ulen && heapscore(buf[ci+1]) < score) { swap(buf[ci+1], buf[i]); i = ci+1; }
507             else break;
508         }
509         return i;
510     }
511 
removeheapvector512     T removeheap()
513     {
514         T e = removeunordered(0);
515         if(ulen) downheap(0);
516         return e;
517     }
518 };
519 
520 typedef vector<char *> cvector;
521 typedef vector<int> ivector;
522 typedef vector<ushort> usvector;
523 
hthash(const char * key)524 static inline uint hthash(const char *key)
525 {
526     uint h = 5381;
527     for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k;    // bernstein k=33 xor
528     return h;
529 }
530 
htcmp(const char * x,const char * y)531 static inline bool htcmp(const char *x, const char *y)
532 {
533     return !strcmp(x, y);
534 }
535 
hthash(int key)536 static inline uint hthash(int key)
537 {
538     return key;
539 }
540 
htcmp(int x,int y)541 static inline bool htcmp(int x, int y)
542 {
543     return x==y;
544 }
545 
546 template <class K, class T> struct hashtable
547 {
548     typedef K key;
549     typedef const K const_key;
550     typedef T value;
551     typedef const T const_value;
552 
553     enum { CHUNKSIZE = 64 };
554 
555     struct chain      { T data; K key; chain *next; };
556     struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; };
557 
558     int size;
559     int numelems;
560     chain **table;
561     chain *enumc;
562 
563     chainchunk *chunks;
564     chain *unused;
565 
566     hashtable(int size = 1<<10)
sizehashtable567       : size(size)
568     {
569         numelems = 0;
570         chunks = NULL;
571         unused = NULL;
572         table = new chain *[size];
573         loopi(size) table[i] = NULL;
574     }
575 
~hashtablehashtable576     ~hashtable()
577     {
578         DELETEA(table);
579         deletechunks();
580     }
581 
inserthashtable582     chain *insert(const K &key, uint h)
583     {
584         if(!unused)
585         {
586             chainchunk *chunk = new chainchunk;
587             chunk->next = chunks;
588             chunks = chunk;
589             loopi(CHUNKSIZE-1) chunk->chains[i].next = &chunk->chains[i+1];
590             chunk->chains[CHUNKSIZE-1].next = unused;
591             unused = chunk->chains;
592         }
593         chain *c = unused;
594         unused = unused->next;
595         c->key = key;
596         c->next = table[h];
597         table[h] = c;
598         numelems++;
599         return c;
600     }
601 
602     #define HTFIND(success, fail) \
603         uint h = hthash(key)&(size-1); \
604         for(chain *c = table[h]; c; c = c->next) \
605         { \
606             if(htcmp(key, c->key)) return (success); \
607         } \
608         return (fail);
609 
accesshashtable610     T *access(const K &key)
611     {
612         HTFIND(&c->data, NULL);
613     }
614 
accesshashtable615     T &access(const K &key, const T &data)
616     {
617         HTFIND(c->data, insert(key, h)->data = data);
618     }
619 
620     T &operator[](const K &key)
621     {
622         HTFIND(c->data, insert(key, h)->data);
623     }
624 
625     #undef HTFIND
626 
removehashtable627     bool remove(const K &key)
628     {
629         uint h = hthash(key)&(size-1);
630         for(chain **p = &table[h], *c = table[h]; c; p = &c->next, c = c->next)
631         {
632             if(htcmp(key, c->key))
633             {
634                 *p = c->next;
635                 c->data.~T();
636                 c->key.~K();
637                 new (&c->data) T;
638                 new (&c->key) K;
639                 c->next = unused;
640                 unused = c;
641                 numelems--;
642                 return true;
643             }
644         }
645         return false;
646     }
647 
deletechunkshashtable648     void deletechunks()
649     {
650         for(chainchunk *nextchunk; chunks; chunks = nextchunk)
651         {
652             nextchunk = chunks->next;
653             delete chunks;
654         }
655     }
656 
clearhashtable657     void clear()
658     {
659         if(!numelems) return;
660         loopi(size) table[i] = NULL;
661         numelems = 0;
662         unused = NULL;
663         deletechunks();
664     }
665 };
666 
667 #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size)  for(hashtable<k,t>::chain *enumc = (ht).table[i]; enumc;) { hashtable<k,t>::const_key &e = enumc->key; t &f = enumc->data; enumc = enumc->next; b; }
668 #define enumerate(ht,t,e,b)       loopi((ht).size) for((ht).enumc = (ht).table[i]; (ht).enumc;) { t &e = (ht).enumc->data;  (ht).enumc = (ht).enumc->next; b; }
669 
670 struct unionfind
671 {
672     struct ufval
673     {
674         int rank, next;
675 
ufvalunionfind::ufval676         ufval() : rank(0), next(-1) {}
677     };
678 
679     vector<ufval> ufvals;
680 
findunionfind681     int find(int k)
682     {
683         if(k>=ufvals.length()) return k;
684         while(ufvals[k].next>=0) k = ufvals[k].next;
685         return k;
686     }
687 
compressfindunionfind688     int compressfind(int k)
689     {
690         if(ufvals[k].next<0) return k;
691         return ufvals[k].next = compressfind(ufvals[k].next);
692     }
693 
uniteunionfind694     void unite (int x, int y)
695     {
696         while(ufvals.length() <= max(x, y)) ufvals.add();
697         x = compressfind(x);
698         y = compressfind(y);
699         if(x==y) return;
700         ufval &xval = ufvals[x], &yval = ufvals[y];
701         if(xval.rank < yval.rank) xval.next = y;
702         else
703         {
704             yval.next = x;
705             if(xval.rank==yval.rank) yval.rank++;
706         }
707     }
708 };
709 
710 template <class T, int SIZE> struct ringbuf
711 {
712     int index, len;
713     T data[SIZE];
714 
ringbufringbuf715     ringbuf() { clear(); }
716 
clearringbuf717     void clear()
718     {
719         index = len = 0;
720     }
721 
emptyringbuf722     bool empty() const { return !len; }
723 
lengthringbuf724     const int length() const { return len; }
725 
addringbuf726     T &add(const T &e)
727     {
728         T &t = (data[index] = e);
729         index++;
730         if(index >= SIZE) index -= SIZE;
731         if(len < SIZE) len++;
732         return t;
733     }
734 
addringbuf735     T &add() { return add(T()); }
736 
737     T &operator[](int i)
738     {
739         i += index - len;
740         return data[i < 0 ? i + SIZE : i%SIZE];
741     }
742 
743     const T &operator[](int i) const
744     {
745         i += index - len;
746         return data[i < 0 ? i + SIZE : i%SIZE];
747     }
748 };
749 
750 template <class T, int SIZE> struct queue
751 {
752     int head, tail, len;
753     T data[SIZE];
754 
queuequeue755     queue() { clear(); }
756 
clearqueue757     void clear() { head = tail = len = 0; }
758 
lengthqueue759     int length() const { return len; }
emptyqueue760     bool empty() const { return !len; }
fullqueue761     bool full() const { return len == SIZE; }
762 
addedqueue763     T &added() { return data[tail > 0 ? tail-1 : SIZE-1]; }
addedqueue764     T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; }
addingqueue765     T &adding() { return data[tail]; }
addingqueue766     T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; }
addqueue767     T &add()
768     {
769         ASSERT(len < SIZE);
770         T &t = data[tail];
771         tail = (tail + 1)%SIZE;
772         len++;
773         return t;
774     }
775 
removingqueue776     T &removing() { return data[head]; }
removingqueue777     T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; }
removequeue778     T &remove()
779     {
780         ASSERT(len > 0);
781         T &t = data[head];
782         head = (head + 1)%SIZE;
783         len--;
784         return t;
785     }
786 };
787 
newstring(size_t l)788 inline char *newstring(size_t l) { return new char[l+1]; }
newstring(const char * s,size_t l)789 inline char *newstring(const char *s, size_t l) { return copystring(newstring(l), s, l+1); }
newstring(const char * s)790 inline char *newstring(const char *s) { return newstring(s, strlen(s));          }
newstringbuf(const char * s)791 inline char *newstringbuf(const char *s) { return newstring(s, MAXSTRLEN-1);       }
792 
itoa(char * s,int i)793 inline void itoa(char *s, int i) { formatstring(s)("%d", i); }
exchangestr(char * o,const char * n)794 inline char *exchangestr(char *o, const char *n) { delete[] o; return newstring(n); }
795 inline char *expandstr(char *o, const char *n, char *delimit = " ")
796 {
797 	int len = strlen(o)+strlen(n)+strlen(delimit)+1;
798 	char *q = new char[len];
799 	copystring(q, o, len);
800 	if(*delimit) concatstring(q, delimit);
801 	concatstring(q, n);
802 	delete[] o;
803 	return q;
804 }
805 
806 #if defined(WIN32) && !defined(__GNUC__)
807 #ifdef _DEBUG
808 //#define _CRTDBG_MAP_ALLOC
809 #include <crtdbg.h>
new(size_t n,const char * fn,int l)810 inline void *__cdecl operator new(size_t n, const char *fn, int l) { return ::operator new(n, 1, fn, l); }
delete(void * p,const char * fn,int l)811 inline void __cdecl operator delete(void *p, const char *fn, int l) { ::operator delete(p, 1, fn, l); }
812 #define new new(__FILE__,__LINE__)
813 #endif
814 #endif
815 
816 const int islittleendian = 1;
817 #ifdef SDL_BYTEORDER
818 #define endianswap16 SDL_Swap16
819 #define endianswap32 SDL_Swap32
820 #else
endianswap16(ushort n)821 inline ushort endianswap16(ushort n) { return (n<<8) | (n>>8); }
endianswap32(uint n)822 inline uint endianswap32(uint n) { return (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000); }
823 #endif
endianswap(T n)824 template<class T> inline T endianswap(T n) { union { T t; uint i; } conv; conv.t = n; conv.i = endianswap32(conv.i); return conv.t; }
825 template<> inline ushort endianswap<ushort>(ushort n) { return endianswap16(n); }
826 template<> inline short endianswap<short>(short n) { return endianswap16(n); }
827 template<> inline uint endianswap<uint>(uint n) { return endianswap32(n); }
828 template<> inline int endianswap<int>(int n) { return endianswap32(n); }
endianswap(T * buf,int len)829 template<class T> inline void endianswap(T *buf, int len) { for(T *end = &buf[len]; buf < end; buf++) *buf = endianswap(*buf); }
endiansame(T n)830 template<class T> inline T endiansame(T n) { return n; }
endiansame(T * buf,int len)831 template<class T> inline void endiansame(T *buf, int len) {}
832 #ifdef SDL_BYTEORDER
833 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
834 #define lilswap endiansame
835 #define bigswap endianswap
836 #else
837 #define lilswap endianswap
838 #define bigswap endiansame
839 #endif
840 #else
lilswap(T n)841 template<class T> inline T lilswap(T n) { return *(const uchar *)&islittleendian ? n : endianswap(n); }
lilswap(T * buf,int len)842 template<class T> inline void lilswap(T *buf, int len) { if(!*(const uchar *)&islittleendian) endianswap(buf, len); }
bigswap(T n)843 template<class T> inline T bigswap(T n) { return *(const uchar *)&islittleendian ? endianswap(n) : n; }
bigswap(T * buf,int len)844 template<class T> inline void bigswap(T *buf, int len) { if(*(const uchar *)&islittleendian) endianswap(buf, len); }
845 #endif
846 
847 /* workaround for some C platforms that have these two functions as macros - not used anywhere */
848 #ifdef getchar
849 #undef getchar
850 #endif
851 #ifdef putchar
852 #undef putchar
853 #endif
854 
855 struct stream
856 {
~streamstream857     virtual ~stream() {}
858     virtual void close() = 0;
859     virtual bool end() = 0;
tellstream860     virtual long tell() { return -1; }
861     virtual bool seek(long offset, int whence = SEEK_SET) { return false; }
862     virtual long size();
readstream863     virtual int read(void *buf, int len) { return 0; }
writestream864     virtual int write(const void *buf, int len) { return 0; }
getcharstream865     virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
putcharstream866     virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
867     virtual bool getline(char *str, int len);
putstringstream868     virtual bool putstring(const char *str) { int len = (int)strlen(str); return write(str, len) == len; }
putlinestream869     virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
printfstream870     virtual int printf(const char *fmt, ...) { return -1; }
getcrcstream871     virtual uint getcrc() { return 0; }
872 
putstream873     template<class T> bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
putlilstream874     template<class T> bool putlil(T n) { return put<T>(lilswap(n)); }
putbigstream875     template<class T> bool putbig(T n) { return put<T>(bigswap(n)); }
876 
getstream877     template<class T> T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
getlilstream878     template<class T> T getlil() { return lilswap(get<T>()); }
getbigstream879     template<class T> T getbig() { return bigswap(get<T>()); }
880 
881 #ifndef STANDALONE
882     SDL_RWops *rwops();
883 #endif
884 };
885 
886 extern char *makerelpath(const char *dir, const char *file, const char *prefix = NULL, const char *cmd = NULL);
887 extern char *makefile(const char *s, const char *e = "", int revision = 0, int start = 1, bool skip = false);
888 extern char *path(char *s);
889 extern char *path(const char *s, bool copy);
890 extern const char *parentdir(const char *directory);
891 extern bool fileexists(const char *path, const char *mode);
892 extern bool createdir(const char *path);
893 extern void sethomedir(const char *dir);
894 extern void appendhomedir(const char *dir);
895 extern void addpackagedir(const char *dir, int flags = 0);
896 extern int maskpackagedirs(int flags);
897 extern const char *findfile(const char *filename, const char *mode);
898 extern stream *openrawfile(const char *filename, const char *mode);
899 extern stream *openzipfile(const char *filename, const char *mode);
900 extern stream *openfile(const char *filename, const char *mode);
901 extern stream *opentempfile(const char *filename, const char *mode);
902 extern stream *opengzfile(const char *filename, const char *mode, stream *file = NULL, int level = Z_BEST_COMPRESSION);
903 extern char *loadfile(const char *fn, int *size);
904 extern bool listdir(const char *dir, const char *ext, vector<char *> &files);
905 extern int listfiles(const char *dir, const char *ext, vector<char *> &files);
906 extern int listzipfiles(const char *dir, const char *ext, vector<char *> &files);
907 extern void backup(const char *fname, const char *ext, int revision = 0, int start = 1);
908 
909 extern void endianswap(void *, int, int);
910 extern void seedMT(uint seed);
911 extern uint randomMT(void);
912 
913 #endif
914 
915