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 typedef unsigned long ulong;
15 typedef signed long long int llong;
16 typedef unsigned long long int ullong;
17 
18 #ifdef _DEBUG
19 #define ASSERT(c) assert(c)
20 #else
21 #define ASSERT(c) if(c) {}
22 #endif
23 
24 #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
25 #define RESTRICT __restrict
26 #else
27 #define RESTRICT
28 #endif
29 
30 #ifdef __GNUC__
31 #define UNUSED __attribute__((unused))
32 #else
33 #define UNUSED
34 #endif
35 
36 void *operator new(size_t, bool);
37 void *operator new[](size_t, bool);
new(size_t,void * p)38 inline void *operator new(size_t, void *p) { return p; }
39 inline void *operator new[](size_t, void *p) { return p; }
delete(void *,void *)40 inline void operator delete(void *, void *) {}
41 inline void operator delete[](void *, void *) {}
42 
43 #ifdef swap
44 #undef swap
45 #endif
46 template<class T>
swap(T & a,T & b)47 static inline void swap(T &a, T &b)
48 {
49     T t = a;
50     a = b;
51     b = t;
52 }
53 #ifdef max
54 #undef max
55 #endif
56 #ifdef min
57 #undef min
58 #endif
59 template<class T>
max(T a,T b)60 static inline T max(T a, T b)
61 {
62     return a > b ? a : b;
63 }
64 template<class T>
max(T a,T b,T c)65 static inline T max(T a, T b, T c)
66 {
67     return max(max(a, b), c);
68 }
69 template<class T>
min(T a,T b)70 static inline T min(T a, T b)
71 {
72     return a < b ? a : b;
73 }
74 template<class T>
min(T a,T b,T c)75 static inline T min(T a, T b, T c)
76 {
77     return min(min(a, b), c);
78 }
79 template<class T, class U>
clamp(T a,U b,U c)80 static inline T clamp(T a, U b, U c)
81 {
82     return max(T(b), min(a, T(c)));
83 }
84 
85 #ifdef __GNUC__
86 #define bitscan(mask) (__builtin_ffs(mask)-1)
87 #else
88 #ifdef WIN32
89 #pragma intrinsic(_BitScanForward)
bitscan(uint mask)90 static inline int bitscan(uint mask)
91 {
92     ulong i;
93     return _BitScanForward(&i, mask) ? i : -1;
94 }
95 #else
bitscan(uint mask)96 static inline int bitscan(uint mask)
97 {
98     if(!mask) return -1;
99     int i = 1;
100     if(!(mask&0xFFFF)) { i += 16; mask >>= 16; }
101     if(!(mask&0xFF)) { i += 8; mask >>= 8; }
102     if(!(mask&0xF)) { i += 4; mask >>= 4; }
103     if(!(mask&3)) { i += 2; mask >>= 2; }
104     return i - (mask&1);
105 }
106 #endif
107 #endif
108 
109 #define rnd(x) ((int)(randomMT()&0x7FFFFFFF)%(x))
110 #define rndscale(x) (float((randomMT()&0x7FFFFFFF)*double(x)/double(0x7FFFFFFF)))
111 #define detrnd(s, x) ((int)(((((uint)(s))*1103515245+12345)>>16)%(x)))
112 #define isnumeric(c) (isdigit(c) || c == '+' || c == '-')
113 
114 #define loop(v,u) for(int v = 0; v < int(u); ++v)
115 #define loopi(u) loop(i,u)
116 #define loopj(u) loop(j,u)
117 #define loopk(u) loop(k,u)
118 #define loopl(u) loop(l,u)
119 #define loopm(u) loop(m,u)
120 #define loopn(u) loop(,u)
121 
122 #define looprev(v,u) for(int v = int(u); --v >= 0;)
123 #define loopirev(u) looprev(i,u)
124 #define loopjrev(u) looprev(j,u)
125 #define loopkrev(u) looprev(k,u)
126 #define looplrev(u) looprev(l,u)
127 #define loopmrev(u) looprev(m,u)
128 #define loopnrev(u) looprev(n,u)
129 
130 #define loopcs(v,m,c,s) \
131     int lcs##v##start = 0; \
132     int lcs##v##end = 0; \
133     if(c > 0) \
134     { \
135         lcs##v##start = clamp(s, 0, m-1); \
136         lcs##v##end = clamp(lcs##v##start+c-1, 0, m-1); \
137     } \
138     else if(c < 0) \
139     { \
140         lcs##v##start = clamp(m-1-max(s, 0)+c+1, 0, m-1); \
141         lcs##v##end = clamp(m-1-max(s, 0), 0, m-1); \
142     } \
143     else \
144     { \
145         lcs##v##start = clamp(s, 0, m-1); \
146         lcs##v##end = max(m-1, 0); \
147     } \
148     for(int v = lcs##v##start; v <= lcs##v##end; v++)
149 
150 #define loopcsi(m,c,s) loopcs(i,m,c,s)
151 #define loopcsj(m,c,s) loopcs(j,m,c,s)
152 #define loopcsk(m,c,s) loopcs(k,m,c,s)
153 #define loopcsl(m,c,s) loopcs(l,m,c,s)
154 
155 #define loopcsrev(v,m,c,s) \
156     int lcs##v##start = 0; \
157     int lcs##v##end = 0; \
158     if(c > 0) \
159     { \
160         lcs##v##start = m-1-clamp(s, 0, m-1); \
161         lcs##v##end = clamp(lcs##v##start-c+1, 0, m-1); \
162     } \
163     else if(c < 0) \
164     { \
165         lcs##v##start = clamp(max(s, 0)-c-1, 0, m-1); \
166         lcs##v##end = clamp(s, 0, m-1); \
167     } \
168     else \
169     { \
170         lcs##v##start = clamp(m-1-s, 0, m-1); \
171         lcs##v##end = 0; \
172     } \
173     for(int v = lcs##v##start; v >= lcs##v##end; v--)
174 
175 #define loopcsirev(m,c,s) loopcsrev(i,m,c,s)
176 #define loopcsjrev(m,c,s) loopcsrev(j,m,c,s)
177 #define loopcskrev(m,c,s) loopcsrev(k,m,c,s)
178 #define loopcslrev(m,c,s) loopcsrev(l,m,c,s)
179 
180 #define DELETEP(p) if(p) { delete   p; p = 0; }
181 #define DELETEA(p) if(p) { delete[] p; p = 0; }
182 
183 #define PI (3.14159265358979f)
184 #define PI2 (2*PI)
185 #define SQRT2 (1.4142135623731f)
186 #define SQRT3 (1.73205080756888f)
187 #define SQRT5 (2.23606797749979f)
188 #define RAD (PI / 180.0f)
189 
190 #ifdef WIN32
191 #ifndef M_PI
192 #define M_PI 3.14159265358979323846
193 #endif
194 #ifndef M_LN2
195 #define M_LN2 0.693147180559945309417
196 #endif
197 
198 #ifdef _MSC_VER
199 #pragma warning (3: 4189)       // local variable is initialized but not referenced
200 #pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
201 #pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
202 #pragma warning (disable: 4355) // 'this' : used in base member initializer list
203 #pragma warning (disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
204 #pragma warning (disable: 4996) // 'strncpy' was declared deprecated
205 #include <direct.h>
206 #define chdir _chdir
207 #define strcasecmp _stricmp
208 #define strncasecmp _strnicmp
209 #define getcwd _getcwd
210 #define PATHDIV '\\'
211 #else
212 #define PATHDIV '/'
213 #endif
214 #else
215 #define __cdecl
216 #define _vsnprintf vsnprintf
217 #define PATHDIV '/'
218 #endif
219 
220 #ifdef __GNUC__
221 #define PRINTFARGS(fmt, args) __attribute__((format(printf, fmt, args)))
222 #else
223 #define PRINTFARGS(fmt, args)
224 #endif
225 
226 // easy safe strings
227 
228 #define MAXSTRLEN 512 // must be at least 512 bytes to comply with rfc1459
229 typedef char string[MAXSTRLEN];
230 
231 #define BIGSTRLEN 4096
232 typedef char bigstring[BIGSTRLEN];
233 
234 #define HUGESTRLEN 8192
235 typedef char hugestring[HUGESTRLEN];
236 
vformatstring(char * d,const char * fmt,va_list v,int len)237 inline void vformatstring(char *d, const char *fmt, va_list v, int len) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; }
vformatstring(char (& d)[N],const char * fmt,va_list v)238 template<size_t N> inline void vformatstring(char (&d)[N], const char *fmt, va_list v) { vformatstring(d, fmt, v, N); }
239 
copystring(char * d,const char * s,size_t len)240 inline char *copystring(char *d, const char *s, size_t len)
241 {
242     size_t slen = min(strlen(s), len-1);
243     memcpy(d, s, slen);
244     d[slen] = 0;
245     return d;
246 }
copystring(char (& d)[N],const char * s)247 template<size_t N> inline char *copystring(char (&d)[N], const char *s) { return copystring(d, s, N); }
248 
concatstring(char * d,const char * s,size_t len)249 inline 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; }
concatstring(char (& d)[N],const char * s)250 template<size_t N> inline char *concatstring(char (&d)[N], const char *s) { return concatstring(d, s, N); }
251 
prependstring(char * d,const char * s,size_t len)252 inline char *prependstring(char *d, const char *s, size_t len)
253 {
254     size_t slen = min(strlen(s), len);
255     memmove(&d[slen], d, min(len - slen, strlen(d) + 1));
256     memcpy(d, s, slen);
257     d[len-1] = 0;
258     return d;
259 }
prependstring(char (& d)[N],const char * s)260 template<size_t N> inline char *prependstring(char (&d)[N], const char *s) { return prependstring(d, s, N); }
261 
262 inline void nformatstring(char *d, int len, const char *fmt, ...) PRINTFARGS(3, 4);
nformatstring(char * d,int len,const char * fmt,...)263 inline void nformatstring(char *d, int len, const char *fmt, ...)
264 {
265     va_list v;
266     va_start(v, fmt);
267     vformatstring(d, fmt, v, len);
268     va_end(v);
269 }
270 
271 template<size_t N> inline void formatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
formatstring(char (& d)[N],const char * fmt,...)272 template<size_t N> inline void formatstring(char (&d)[N], const char *fmt, ...)
273 {
274     va_list v;
275     va_start(v, fmt);
276     vformatstring(d, fmt, v, int(N));
277     va_end(v);
278 }
279 
280 template<size_t N> inline void concformatstring(char (&d)[N], const char *fmt, ...) PRINTFARGS(2, 3);
concformatstring(char (& d)[N],const char * fmt,...)281 template<size_t N> inline void concformatstring(char (&d)[N], const char *fmt, ...)
282 {
283     va_list v;
284     va_start(v, fmt);
285     int len = strlen(d);
286     vformatstring(d + len, fmt, v, int(N) - len);
287     va_end(v);
288 }
289 
290 extern char *tempformatstring(const char *fmt, ...) PRINTFARGS(1, 2);
291 
292 #define defformatstring(d,...) string d; formatstring(d, __VA_ARGS__)
293 #define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
294 #define stringz(d) string d; d[0] = 0;
295 
296 #define defformatbigstring(d,...) bigstring d; formatstring(d, __VA_ARGS__)
297 #define defvformatbigstring(d,last,fmt) bigstring d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
298 #define bigstringz(d) bigstring d; d[0] = 0;
299 
300 #define defformathugestring(d,...) hugestring d; formatstring(d, __VA_ARGS__)
301 #define defvformathugestring(d,last,fmt) hugestring d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
302 #define hugestringz(d) hugestring d; d[0] = 0;
303 
matchstring(const char * s,size_t len,const char (& d)[N])304 template<size_t N> inline bool matchstring(const char *s, size_t len, const char (&d)[N])
305 {
306     return len == N-1 && !memcmp(s, d, N-1);
307 }
308 
newstring(size_t l)309 inline char *newstring(size_t l)                { return new char[l+1]; }
newstring(const char * s,size_t l)310 inline char *newstring(const char *s, size_t l) { return copystring(newstring(l), s, l+1); }
newstring(const char * s)311 inline char *newstring(const char *s)           { if(!s) s = ""; size_t l = strlen(s); char *d = newstring(l); memcpy(d, s, l+1); return d; }
312 
newconcatstring(const char * s,const char * t)313 inline char *newconcatstring(const char *s, const char *t)
314 {
315     size_t slen = strlen(s), tlen = strlen(t);
316     char *r = newstring(slen + tlen);
317     memcpy(r, s, slen);
318     memcpy(&r[slen], t, tlen);
319     r[slen+tlen] = '\0';
320     return r;
321 }
322 
323 #define loopv(v)    for(int i = 0; i<(v).length(); i++)
324 #define loopvj(v)   for(int j = 0; j<(v).length(); j++)
325 #define loopvk(v)   for(int k = 0; k<(v).length(); k++)
326 #define loopvl(v)   for(int l = 0; l<(v).length(); l++)
327 #define loopvm(v)   for(int m = 0; m<(v).length(); m++)
328 #define loopvn(v)   for(int n = 0; n<(v).length(); n++)
329 #define loopvrev(v) for(int i = (v).length()-1; i>=0; i--)
330 #define loopvjrev(v) for(int j = (v).length()-1; j>=0; j--)
331 #define loopvkrev(v) for(int k = (v).length()-1; k>=0; k--)
332 #define loopvlrev(v) for(int l = (v).length()-1; l>=0; l--)
333 #define loopvmrev(v) for(int m = (v).length()-1; m>=0; m--)
334 #define loopvnrev(v) for(int n = (v).length()-1; n>=0; n--)
335 #define loopcsv(u,c,s) loopcs(i,(u).length(),c,s)
336 #define loopcsvj(u,c,s) loopcs(j,(u).length(),c,s)
337 #define loopcsvk(u,c,s) loopcs(k,(u).length(),c,s)
338 #define loopcsvl(u,c,s) loopcs(l,(u).length(),c,s)
339 #define loopcsvm(u,c,s) loopcs(m,(u).length(),c,s)
340 #define loopcsvn(u,c,s) loopcs(n,(u).length(),c,s)
341 #define loopcsvrev(u,c,s) loopcsrev(i,(u).length(),c,s)
342 #define loopcsvjrev(u,c,s) loopcsrev(j,(u).length(),c,s)
343 #define loopcsvkrev(u,c,s) loopcsrev(k,(u).length(),c,s)
344 #define loopcsvlrev(u,c,s) loopcsrev(l,(u).length(),c,s)
345 #define loopcsvmrev(u,c,s) loopcsrev(m,(u).length(),c,s)
346 #define loopcsvnrev(u,c,s) loopcsrev(n,(u).length(),c,s)
347 
memclear(T * p,size_t n)348 template<class T> inline void memclear(T *p, size_t n) { memset((void *)p, 0, n * sizeof(T)); }
memclear(T & p)349 template<class T> inline void memclear(T &p) { memset((void *)&p, 0, sizeof(T)); }
memclear(T (& p)[N])350 template<class T, size_t N> inline void memclear(T (&p)[N]) { memset((void *)p, 0, N * sizeof(T)); }
351 
352 template <class T>
353 struct databuf
354 {
355     enum
356     {
357         OVERREAD  = 1<<0,
358         OVERWROTE = 1<<1
359     };
360 
361     T *buf;
362     int len, maxlen;
363     uchar flags;
364 
databufdatabuf365     databuf() : buf(NULL), len(0), maxlen(0), flags(0) {}
366 
367     template<class U>
databufdatabuf368     databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
369 
resetdatabuf370     void reset()
371     {
372         len = 0;
373         flags = 0;
374     }
375 
resetdatabuf376     void reset(T *buf_, int maxlen_)
377     {
378         reset();
379         buf = buf_;
380         maxlen = maxlen_;
381     }
382 
getdatabuf383     const T &get()
384     {
385         static const T overreadval = 0;
386         if(len<maxlen) return buf[len++];
387         flags |= OVERREAD;
388         return overreadval;
389     }
390 
subbufdatabuf391     databuf subbuf(int sz)
392     {
393         sz = clamp(sz, 0, maxlen-len);
394         len += sz;
395         return databuf(&buf[len-sz], sz);
396     }
397 
paddatabuf398     T *pad(int numvals)
399     {
400         T *vals = &buf[len];
401         len += min(numvals, maxlen-len);
402         return vals;
403     }
404 
putdatabuf405     void put(const T &val)
406     {
407         if(len<maxlen) buf[len++] = val;
408         else flags |= OVERWROTE;
409     }
410 
putdatabuf411     void put(const T *vals, int numvals)
412     {
413         if(maxlen - len < numvals)
414         {
415             numvals = maxlen - len;
416             flags |= OVERWROTE;
417         }
418         memcpy(&buf[len], (const void *)vals, numvals*sizeof(T));
419         len += numvals;
420     }
421 
getdatabuf422     int get(T *vals, int numvals)
423     {
424         if(maxlen - len < numvals)
425         {
426             numvals = maxlen - len;
427             flags |= OVERREAD;
428         }
429         memcpy(vals, (void *)&buf[len], numvals*sizeof(T));
430         len += numvals;
431         return numvals;
432     }
433 
offsetdatabuf434     void offset(int n)
435     {
436         n = min(n, maxlen);
437         buf += n;
438         maxlen -= n;
439         len = max(len-n, 0);
440     }
441 
getbufdatabuf442     T *getbuf() const { return buf; }
emptydatabuf443     bool empty() const { return len==0; }
lengthdatabuf444     int length() const { return len; }
remainingdatabuf445     int remaining() const { return maxlen-len; }
overreaddatabuf446     bool overread() const { return (flags&OVERREAD)!=0; }
overwrotedatabuf447     bool overwrote() const { return (flags&OVERWROTE)!=0; }
448 
checkdatabuf449     bool check(int n) { return remaining() >= n; }
450 
forceoverreaddatabuf451     void forceoverread()
452     {
453         len = maxlen;
454         flags |= OVERREAD;
455     }
456 };
457 
458 typedef databuf<char> charbuf;
459 typedef databuf<uchar> ucharbuf;
460 
461 struct packetbuf : ucharbuf
462 {
463     ENetPacket *packet;
464     int growth;
465 
packetbufpacketbuf466     packetbuf(ENetPacket *packet) : ucharbuf(packet->data, packet->dataLength), packet(packet), growth(0) {}
growthpacketbuf467     packetbuf(int growth, int pflags = 0) : growth(growth)
468     {
469         packet = enet_packet_create(NULL, growth, pflags);
470         buf = (uchar *)packet->data;
471         maxlen = packet->dataLength;
472     }
~packetbufpacketbuf473     ~packetbuf() { cleanup(); }
474 
reliablepacketbuf475     void reliable() { packet->flags |= ENET_PACKET_FLAG_RELIABLE; }
476 
resizepacketbuf477     void resize(int n)
478     {
479         enet_packet_resize(packet, n);
480         buf = (uchar *)packet->data;
481         maxlen = packet->dataLength;
482     }
483 
checkspacepacketbuf484     void checkspace(int n)
485     {
486         if(len + n > maxlen && packet && growth > 0) resize(max(len + n, maxlen + growth));
487     }
488 
subbufpacketbuf489     ucharbuf subbuf(int sz)
490     {
491         checkspace(sz);
492         return ucharbuf::subbuf(sz);
493     }
494 
putpacketbuf495     void put(const uchar &val)
496     {
497         checkspace(1);
498         ucharbuf::put(val);
499     }
500 
putpacketbuf501     void put(const uchar *vals, int numvals)
502     {
503         checkspace(numvals);
504         ucharbuf::put(vals, numvals);
505     }
506 
finalizepacketbuf507     ENetPacket *finalize()
508     {
509         resize(len);
510         return packet;
511     }
512 
cleanuppacketbuf513     void cleanup()
514     {
515         if(growth > 0 && packet && !packet->referenceCount) { enet_packet_destroy(packet); packet = NULL; buf = NULL; len = maxlen = 0; }
516     }
517 };
518 
519 template<class T>
heapscore(const T & n)520 static inline float heapscore(const T &n) { return n; }
521 
522 struct sortless
523 {
operatorsortless524     template<class T> bool operator()(const T &x, const T &y) const { return x < y; }
operatorsortless525     bool operator()(char *x, char *y) const { return strcmp(x, y) < 0; }
operatorsortless526     bool operator()(const char *x, const char *y) const { return strcmp(x, y) < 0; }
527 };
528 
529 struct sortnameless
530 {
operatorsortnameless531     template<class T> bool operator()(const T &x, const T &y) const { return sortless()(x.name, y.name); }
operatorsortnameless532     template<class T> bool operator()(T *x, T *y) const { return sortless()(x->name, y->name); }
operatorsortnameless533     template<class T> bool operator()(const T *x, const T *y) const { return sortless()(x->name, y->name); }
534 };
535 
536 template<class T, class F>
insertionsort(T * start,T * end,F fun)537 static inline void insertionsort(T *start, T *end, F fun)
538 {
539     for(T *i = start+1; i < end; i++)
540     {
541         if(fun(*i, i[-1]))
542         {
543             T tmp = *i;
544             *i = i[-1];
545             T *j = i-1;
546             for(; j > start && fun(tmp, j[-1]); --j)
547                 *j = j[-1];
548             *j = tmp;
549         }
550     }
551 
552 }
553 
554 template<class T, class F>
insertionsort(T * buf,int n,F fun)555 static inline void insertionsort(T *buf, int n, F fun)
556 {
557     insertionsort(buf, buf+n, fun);
558 }
559 
560 template<class T>
insertionsort(T * buf,int n)561 static inline void insertionsort(T *buf, int n)
562 {
563     insertionsort(buf, buf+n, sortless());
564 }
565 
566 template<class T, class F>
quicksort(T * start,T * end,F fun)567 static inline void quicksort(T *start, T *end, F fun)
568 {
569     while(end-start > 10)
570     {
571         T *mid = &start[(end-start)/2], *i = start+1, *j = end-2, pivot;
572         if(fun(*start, *mid)) /* start < mid */
573         {
574             if(fun(end[-1], *start)) { pivot = *start; *start = end[-1]; end[-1] = *mid; } /* end < start < mid */
575             else if(fun(end[-1], *mid)) { pivot = end[-1]; end[-1] = *mid; } /* start <= end < mid */
576             else { pivot = *mid; } /* start < mid <= end */
577         }
578         else if(fun(*start, end[-1])) { pivot = *start; *start = *mid; } /*mid <= start < end */
579         else if(fun(*mid, end[-1])) { pivot = end[-1]; end[-1] = *start; *start = *mid; } /* mid < end <= start */
580         else { pivot = *mid; swap(*start, end[-1]); }  /* end <= mid <= start */
581         *mid = end[-2];
582         do
583         {
584             while(fun(*i, pivot)) if(++i >= j) goto partitioned;
585             while(fun(pivot, *--j)) if(i >= j) goto partitioned;
586             swap(*i, *j);
587         }
588         while(++i < j);
589     partitioned:
590         end[-2] = *i;
591         *i = pivot;
592 
593         if(i-start < end-(i+1))
594         {
595             quicksort(start, i, fun);
596             start = i+1;
597         }
598         else
599         {
600             quicksort(i+1, end, fun);
601             end = i;
602         }
603     }
604 
605     insertionsort(start, end, fun);
606 }
607 
608 template<class T, class F>
quicksort(T * buf,int n,F fun)609 static inline void quicksort(T *buf, int n, F fun)
610 {
611     quicksort(buf, buf+n, fun);
612 }
613 
614 template<class T>
quicksort(T * buf,int n)615 static inline void quicksort(T *buf, int n)
616 {
617     quicksort(buf, buf+n, sortless());
618 }
619 
620 template<class T> struct isclass
621 {
622     template<class C> static char test(void (C::*)(void));
623     template<class C> static int test(...);
624     enum { yes = sizeof(test<T>(0)) == 1 ? 1 : 0, no = yes^1 };
625 };
626 
hthash(const char * key)627 static inline uint hthash(const char *key)
628 {
629     uint h = 5381;
630     for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k;    // bernstein k=33 xor
631     return h;
632 }
633 
htcmp(const char * x,const char * y)634 static inline bool htcmp(const char *x, const char *y)
635 {
636     return !strcmp(x, y);
637 }
638 
639 struct stringslice
640 {
641     const char *str;
642     int len;
stringslicestringslice643     stringslice() {}
stringslicestringslice644     stringslice(const char *str, int len) : str(str), len(len) {}
stringslicestringslice645     stringslice(const char *str, const char *end) : str(str), len(int(end-str)) {}
646 
endstringslice647     const char *end() const { return &str[len]; }
648 };
649 
newstring(const stringslice & s)650 inline char *newstring(const stringslice &s) { return newstring(s.str, s.len); }
stringptr(const char * s)651 inline const char *stringptr(const char *s) { return s; }
stringptr(const stringslice & s)652 inline const char *stringptr(const stringslice &s) { return s.str; }
stringlen(const char * s)653 inline int stringlen(const char *s) { return int(strlen(s)); }
stringlen(const stringslice & s)654 inline int stringlen(const stringslice &s) { return s.len; }
655 
copystring(char * d,const stringslice & s,size_t len)656 inline char *copystring(char *d, const stringslice &s, size_t len)
657 {
658     size_t slen = min(size_t(s.len), len-1);
659     memcpy(d, s.str, slen);
660     d[slen] = 0;
661     return d;
662 }
copystring(char (& d)[N],const stringslice & s)663 template<size_t N> inline char *copystring(char (&d)[N], const stringslice &s) { return copystring(d, s, N); }
664 
memhash(const void * ptr,int len)665 static inline uint memhash(const void *ptr, int len)
666 {
667     const uchar *data = (const uchar *)ptr;
668     uint h = 5381;
669     loopi(len) h = ((h<<5)+h)^data[i];
670     return h;
671 }
672 
hthash(const stringslice & s)673 static inline uint hthash(const stringslice &s) { return memhash(s.str, s.len); }
674 
htcmp(const stringslice & x,const char * y)675 static inline bool htcmp(const stringslice &x, const char *y)
676 {
677     return x.len == (int)strlen(y) && !memcmp(x.str, y, x.len);
678 }
679 
hthash(int key)680 static inline uint hthash(int key)
681 {
682     return key;
683 }
684 
htcmp(int x,int y)685 static inline bool htcmp(int x, int y)
686 {
687     return x==y;
688 }
689 
690 #ifndef STANDALONE
hthash(GLuint key)691 static inline uint hthash(GLuint key)
692 {
693     return key;
694 }
695 
htcmp(GLuint x,GLuint y)696 static inline bool htcmp(GLuint x, GLuint y)
697 {
698     return x==y;
699 }
700 #endif
701 
702 template <class T> struct vector
703 {
704     static const int MINSIZE = 8;
705 
706     T *buf;
707     int alen, ulen;
708 
vectorvector709     vector() : buf(NULL), alen(0), ulen(0)
710     {
711     }
712 
vectorvector713     vector(const vector &v) : buf(NULL), alen(0), ulen(0)
714     {
715         *this = v;
716     }
717 
~vectorvector718     ~vector() { shrink(0); if(buf) delete[] (uchar *)buf; }
719 
720     vector<T> &operator=(const vector<T> &v)
721     {
722         shrink(0);
723         if(v.length() > alen) growbuf(v.length());
724         loopv(v) add(v[i]);
725         return *this;
726     }
727 
addvector728     T &add(const T &x)
729     {
730         if(ulen==alen) growbuf(ulen+1);
731         new (&buf[ulen]) T(x);
732         return buf[ulen++];
733     }
734 
addvector735     T &add()
736     {
737         if(ulen==alen) growbuf(ulen+1);
738         new (&buf[ulen]) T;
739         return buf[ulen++];
740     }
741 
addvector742     void add(const T &x, int n)
743     {
744         if(n <= 0) return;
745         growbuf(ulen+n);
746         loopi(n) new (&buf[ulen++]) T(x);
747     }
748 
dupvector749     T &dup()
750     {
751         if(ulen==alen) growbuf(ulen+1);
752         new (&buf[ulen]) T(buf[ulen-1]);
753         return buf[ulen++];
754     }
755 
movevector756     void move(vector<T> &v)
757     {
758         if(!ulen)
759         {
760             swap(buf, v.buf);
761             swap(ulen, v.ulen);
762             swap(alen, v.alen);
763         }
764         else
765         {
766             growbuf(ulen+v.ulen);
767             if(v.ulen) memcpy(&buf[ulen], (void  *)v.buf, v.ulen*sizeof(T));
768             ulen += v.ulen;
769             v.ulen = 0;
770         }
771     }
772 
inrangevector773     bool inrange(size_t i) const { return i<size_t(ulen); }
inrangevector774     bool inrange(int i) const { return i>=0 && i<ulen; }
775 
popvector776     T &pop() { return buf[--ulen]; }
lastvector777     T &last() { return buf[ulen-1]; }
firstvector778     T &first() { return buf[0]; }
dropvector779     void drop() { ulen--; buf[ulen].~T(); }
emptyvector780     bool empty() const { return ulen==0; }
781 
capacityvector782     int capacity() const { return alen; }
lengthvector783     int length() const { return ulen; }
784     T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; }
785     const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; }
786 
disownvector787     T *disown() { T *r = buf; buf = NULL; alen = ulen = 0; return r; }
788 
shrinkvector789     void shrink(int i) { ASSERT(i<=ulen); if(isclass<T>::no) ulen = i; else while(ulen>i) drop(); }
setsizevector790     void setsize(int i) { ASSERT(i<=ulen); ulen = i; }
791 
792     void deletecontents(int n = 0) { while(ulen > n) delete pop(); }
793     void deletearrays(int n = 0) { while(ulen > n) delete[] pop(); }
794 
getbufvector795     T *getbuf() { return buf; }
getbufvector796     const T *getbuf() const { return buf; }
inbufvector797     bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; }
798 
799     template<class F>
800     void sort(F fun, int i = 0, int n = -1)
801     {
802         quicksort(&buf[i], n < 0 ? ulen-i : n, fun);
803     }
804 
sortvector805     void sort() { sort(sortless()); }
sortnamevector806     void sortname() { sort(sortnameless()); }
807 
growbufvector808     void growbuf(int sz)
809     {
810         int olen = alen;
811         if(alen <= 0) alen = max(MINSIZE, sz);
812         else while(alen < sz) alen += alen/2;
813         if(alen <= olen) return;
814         uchar *newbuf = new uchar[alen*sizeof(T)];
815         if(olen > 0)
816         {
817             if(ulen > 0) memcpy(newbuf, (void *)buf, ulen*sizeof(T));
818             delete[] (uchar *)buf;
819         }
820         buf = (T *)newbuf;
821     }
822 
reservevector823     databuf<T> reserve(int sz)
824     {
825         if(alen-ulen < sz) growbuf(ulen+sz);
826         return databuf<T>(&buf[ulen], sz);
827     }
828 
advancevector829     void advance(int sz)
830     {
831         ulen += sz;
832     }
833 
addbufvector834     void addbuf(const databuf<T> &p)
835     {
836         advance(p.length());
837     }
838 
padvector839     T *pad(int n)
840     {
841         T *buf = reserve(n).buf;
842         advance(n);
843         return buf;
844     }
845 
putvector846     void put(const T &v) { add(v); }
847 
putvector848     void put(const T *v, int n)
849     {
850         databuf<T> buf = reserve(n);
851         buf.put(v, n);
852         addbuf(buf);
853     }
854 
removevector855     void remove(int i, int n)
856     {
857         for(int p = i+n; p<ulen; p++) buf[p-n] = buf[p];
858         ulen -= n;
859     }
860 
removevector861     T remove(int i)
862     {
863         T e = buf[i];
864         for(int p = i+1; p<ulen; p++) buf[p-1] = buf[p];
865         ulen--;
866         return e;
867     }
868 
removeunorderedvector869     T removeunordered(int i)
870     {
871         T e = buf[i];
872         ulen--;
873         if(ulen>0) buf[i] = buf[ulen];
874         return e;
875     }
876 
877     template<class U>
findvector878     int find(const U &o)
879     {
880         loopi(ulen) if(buf[i]==o) return i;
881         return -1;
882     }
883 
adduniquevector884     void addunique(const T &o)
885     {
886         if(find(o) < 0) add(o);
887     }
888 
removeobjvector889     void removeobj(const T &o)
890     {
891         loopi(ulen) if(buf[i] == o)
892         {
893             int dst = i;
894             for(int j = i+1; j < ulen; j++) if(!(buf[j] == o)) buf[dst++] = buf[j];
895             setsize(dst);
896             break;
897         }
898     }
899 
replacewithlastvector900     void replacewithlast(const T &o)
901     {
902         if(!ulen) return;
903         loopi(ulen-1) if(buf[i]==o)
904         {
905             buf[i] = buf[ulen-1];
906             break;
907         }
908         ulen--;
909     }
910 
insertvector911     T &insert(int i, const T &e)
912     {
913         add(T());
914         for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1];
915         buf[i] = e;
916         return buf[i];
917     }
918 
insertvector919     T *insert(int i, const T *e, int n)
920     {
921         if(alen-ulen < n) growbuf(ulen+n);
922         loopj(n) add(T());
923         for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n];
924         loopj(n) buf[i+j] = e[j];
925         return &buf[i];
926     }
927 
reversevector928     void reverse()
929     {
930         loopi(ulen/2) swap(buf[i], buf[ulen-1-i]);
931     }
932 
heapparentvector933     static int heapparent(int i) { return (i - 1) >> 1; }
heapchildvector934     static int heapchild(int i) { return (i << 1) + 1; }
935 
buildheapvector936     void buildheap()
937     {
938         for(int i = ulen/2; i >= 0; i--) downheap(i);
939     }
940 
upheapvector941     int upheap(int i)
942     {
943         float score = heapscore(buf[i]);
944         while(i > 0)
945         {
946             int pi = heapparent(i);
947             if(score >= heapscore(buf[pi])) break;
948             swap(buf[i], buf[pi]);
949             i = pi;
950         }
951         return i;
952     }
953 
addheapvector954     T &addheap(const T &x)
955     {
956         add(x);
957         return buf[upheap(ulen-1)];
958     }
959 
downheapvector960     int downheap(int i)
961     {
962         float score = heapscore(buf[i]);
963         for(;;)
964         {
965             int ci = heapchild(i);
966             if(ci >= ulen) break;
967             float cscore = heapscore(buf[ci]);
968             if(score > cscore)
969             {
970                if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; }
971                else { swap(buf[ci], buf[i]); i = ci; }
972             }
973             else if(ci+1 < ulen && heapscore(buf[ci+1]) < score) { swap(buf[ci+1], buf[i]); i = ci+1; }
974             else break;
975         }
976         return i;
977     }
978 
removeheapvector979     T removeheap()
980     {
981         T e = removeunordered(0);
982         if(ulen) downheap(0);
983         return e;
984     }
985 
986     template<class K>
htfindvector987     int htfind(const K &key)
988     {
989         loopi(ulen) if(htcmp(key, buf[i])) return i;
990         return -1;
991     }
992 
993     #define UNIQUE(overwrite, cleanup) \
994         for(int i = 1; i < ulen; i++) if(htcmp(buf[i-1], buf[i])) \
995         { \
996             int n = i; \
997             while(++i < ulen) if(!htcmp(buf[n-1], buf[i])) { overwrite; n++; } \
998             cleanup; \
999             break; \
1000         }
uniquevector1001     void unique() // contents must be initially sorted
1002     {
1003         UNIQUE(buf[n] = buf[i], setsize(n));
1004     }
uniquedeletecontentsvector1005     void uniquedeletecontents()
1006     {
1007         UNIQUE(swap(buf[n], buf[i]), deletecontents(n));
1008     }
uniquedeletearraysvector1009     void uniquedeletearrays()
1010     {
1011         UNIQUE(swap(buf[n], buf[i]), deletearrays(n));
1012     }
1013     #undef UNIQUE
1014 };
1015 
1016 template <class T> struct smallvector
1017 {
1018     T *buf;
1019     int len;
1020 
smallvectorsmallvector1021     smallvector() : buf(NULL), len(0)
1022     {
1023     }
1024 
smallvectorsmallvector1025     smallvector(const smallvector &v) : buf(NULL), len(0)
1026     {
1027         *this = v;
1028     }
1029 
~smallvectorsmallvector1030     ~smallvector() { shrink(0); }
1031 
1032     smallvector<T> &operator=(const smallvector<T> &v)
1033     {
1034         shrink(0);
1035         growbuf(v.length());
1036         loopv(v) buf[i] = v[i];
1037         return *this;
1038     }
1039 
growbufsmallvector1040     void growbuf(int sz)
1041     {
1042         len = max(sz, 0);
1043         if(len)
1044         {
1045             buf = (T *)realloc(buf, len*sizeof(T));
1046             if(!buf) abort();
1047         }
1048         else if(buf) { free(buf); buf = NULL; }
1049     }
1050 
addsmallvector1051     T &add(const T &x)
1052     {
1053         growbuf(len+1);
1054         new (&buf[len-1]) T(x);
1055         return buf[len-1];
1056     }
1057 
addsmallvector1058     T &add()
1059     {
1060         growbuf(len+1);
1061         new (&buf[len-1]) T;
1062         return buf[len-1];
1063     }
1064 
addsmallvector1065     void add(const T &x, int n)
1066     {
1067         if(n <= 0) return;
1068         growbuf(len+n);
1069         while(n > 0) new (&buf[len-n--]) T(x);
1070     }
1071 
putsmallvector1072     void put(const T &v) { add(v); }
1073 
putsmallvector1074     void put(const T *v, int n)
1075     {
1076         if(n <= 0) return;
1077         growbuf(len + n);
1078         memcpy(&buf[len-n], v, n*sizeof(T));
1079     }
1080 
writesmallvector1081     void write(int i, const T *v, int n)
1082     {
1083         if(i < 0)
1084         {
1085             n += i;
1086             v -= i;
1087             i = 0;
1088         }
1089         if(n <= 0 || i > len) return;
1090         if(i + n > len) growbuf(i + n);
1091         memcpy(&buf[i], v, n*sizeof(T));
1092     }
1093 
writesmallvector1094     void write(int i, const smallvector<T>& v)
1095     {
1096         write(i, v.getbuf(), v.length());
1097     }
1098 
writesmallvector1099     void write(int i, const smallvector<T>& v, int n)
1100     {
1101         write(i, v.getbuf(), min(v.length(), n));
1102     }
1103 
shrinksmallvector1104     void shrink(int i)
1105     {
1106         ASSERT(i<=len);
1107         if(i >= len) return;
1108         if(isclass<T>::yes) for(int j = i; j < len; j++) buf[j].~T();
1109         growbuf(i);
1110     }
1111 
setsizesmallvector1112     void setsize(int i)
1113     {
1114         ASSERT(i<=len);
1115         if(i >= len) return;
1116         growbuf(i);
1117     }
1118 
setsizesmallvector1119     void setsize(int i, const T &x)
1120     {
1121         if(i >= len) add(x, i - len);
1122         else growbuf(i);
1123     }
1124 
deletecontentssmallvector1125     void deletecontents()
1126     {
1127         for(int i = 0; i < len; i++) delete buf[i];
1128         setsize(0);
1129     }
1130 
deletearrayssmallvector1131     void deletearrays()
1132     {
1133         for(int i = 0; i < len; i++) delete[] buf[i];
1134         setsize(0);
1135     }
1136 
removesmallvector1137     T remove(int i)
1138     {
1139         T e = buf[i];
1140         for(int p = i+1; p<len; p++) buf[p-1] = buf[p];
1141         growbuf(len-1);
1142         return e;
1143     }
1144 
removeunorderedsmallvector1145     T removeunordered(int i)
1146     {
1147         T e = buf[i];
1148         if(len>1) buf[i] = buf[len-1];
1149         growbuf(len-1);
1150         return e;
1151     }
1152 
dropsmallvector1153     void drop() { buf[len-1].~T(); growbuf(len-1); }
1154 
insertsmallvector1155     T &insert(int i, const T &e)
1156     {
1157         add(T());
1158         for(int p = len-1; p>i; p--) buf[p] = buf[p-1];
1159         buf[i] = e;
1160         return buf[i];
1161     }
1162 
insertsmallvector1163     T *insert(int i, const T *e, int n)
1164     {
1165         growbuf(len+n);
1166         loopj(n) add(T());
1167         for(int p = len-1; p>=i+n; p--) buf[p] = buf[p-n];
1168         loopj(n) buf[i+j] = e[j];
1169         return &buf[i];
1170     }
1171 
inrangesmallvector1172     bool inrange(size_t i) const { return i<size_t(len); }
inrangesmallvector1173     bool inrange(int i) const { return i>=0 && i<len; }
1174 
lastsmallvector1175     T &last() { return buf[len-1]; }
firstsmallvector1176     T &first() { return buf[0]; }
emptysmallvector1177     bool empty() const { return len==0; }
lengthsmallvector1178     int length() const { return len; }
1179     T &operator[](int i) { ASSERT(i>=0 && i<len); return buf[i]; }
1180     const T &operator[](int i) const { ASSERT(i >= 0 && i<len); return buf[i]; }
getbufsmallvector1181     T *getbuf() { return buf; }
getbufsmallvector1182     const T *getbuf() const { return buf; }
inbufsmallvector1183     bool inbuf(const T *e) const { return e >= buf && e < &buf[len]; }
1184 
1185     template<class U>
findsmallvector1186     int find(const U &o)
1187     {
1188         loopi(len) if(buf[i]==o) return i;
1189         return -1;
1190     }
1191 
1192     template<class K>
htfindsmallvector1193     int htfind(const K &key)
1194     {
1195         loopi(len) if(htcmp(key, buf[i])) return i;
1196         return -1;
1197     }
1198 };
1199 
1200 template<class H, class E, class K, class T> struct hashbase
1201 {
1202     typedef E elemtype;
1203     typedef K keytype;
1204     typedef T datatype;
1205 
1206     enum { CHUNKSIZE = 64 };
1207 
1208     struct chain { E elem; chain *next; };
1209     struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; };
1210 
1211     int size;
1212     int numelems;
1213     chain **chains;
1214 
1215     chainchunk *chunks;
1216     chain *unused;
1217 
1218     enum { DEFAULTSIZE = 1<<10 };
1219 
1220     hashbase(int size = DEFAULTSIZE)
sizehashbase1221       : size(size)
1222     {
1223         numelems = 0;
1224         chunks = NULL;
1225         unused = NULL;
1226         chains = new chain *[size];
1227         memset(chains, 0, size*sizeof(chain *));
1228     }
1229 
~hashbasehashbase1230     ~hashbase()
1231     {
1232         DELETEA(chains);
1233         deletechunks();
1234     }
1235 
inserthashbase1236     chain *insert(uint h)
1237     {
1238         if(!unused)
1239         {
1240             chainchunk *chunk = new chainchunk;
1241             chunk->next = chunks;
1242             chunks = chunk;
1243             loopi(CHUNKSIZE-1) chunk->chains[i].next = &chunk->chains[i+1];
1244             chunk->chains[CHUNKSIZE-1].next = unused;
1245             unused = chunk->chains;
1246         }
1247         chain *c = unused;
1248         unused = unused->next;
1249         c->next = chains[h];
1250         chains[h] = c;
1251         numelems++;
1252         return c;
1253     }
1254 
1255     template<class U>
inserthashbase1256     T &insert(uint h, const U &key)
1257     {
1258         chain *c = insert(h);
1259         H::setkey(c->elem, key);
1260         return H::getdata(c->elem);
1261     }
1262 
1263     #define HTFIND(success, fail) \
1264         uint h = hthash(key)&(this->size-1); \
1265         for(chain *c = this->chains[h]; c; c = c->next) \
1266         { \
1267             if(htcmp(key, H::getkey(c->elem))) return success H::getdata(c->elem); \
1268         } \
1269         return (fail);
1270 
1271     template<class U>
accesshashbase1272     T *access(const U &key)
1273     {
1274         HTFIND(&, NULL);
1275     }
1276 
1277     template<class U, class V>
accesshashbase1278     T &access(const U &key, const V &elem)
1279     {
1280         HTFIND( , insert(h, key) = elem);
1281     }
1282 
1283     template<class U>
1284     T &operator[](const U &key)
1285     {
1286         HTFIND( , insert(h, key));
1287     }
1288 
1289     template<class U>
findhashbase1290     T &find(const U &key, T &notfound)
1291     {
1292         HTFIND( , notfound);
1293     }
1294 
1295     template<class U>
findhashbase1296     const T &find(const U &key, const T &notfound)
1297     {
1298         HTFIND( , notfound);
1299     }
1300 
1301     template<class U>
removehashbase1302     bool remove(const U &key)
1303     {
1304         uint h = hthash(key)&(size-1);
1305         for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next)
1306         {
1307             if(htcmp(key, H::getkey(c->elem)))
1308             {
1309                 *p = c->next;
1310                 c->elem.~E();
1311                 new (&c->elem) E;
1312                 c->next = unused;
1313                 unused = c;
1314                 numelems--;
1315                 return true;
1316             }
1317         }
1318         return false;
1319     }
1320 
recyclehashbase1321     void recycle()
1322     {
1323         if(!numelems) return;
1324         loopi(size)
1325         {
1326             chain *c = chains[i];
1327             if(!c) continue;
1328             for(;;)
1329             {
1330                 htrecycle(c->elem);
1331                 if(!c->next) break;
1332                 c = c->next;
1333             }
1334             c->next = unused;
1335             unused = chains[i];
1336             chains[i] = NULL;
1337         }
1338         numelems = 0;
1339     }
1340 
deletechunkshashbase1341     void deletechunks()
1342     {
1343         for(chainchunk *nextchunk; chunks; chunks = nextchunk)
1344         {
1345             nextchunk = chunks->next;
1346             delete chunks;
1347         }
1348     }
1349 
clearhashbase1350     void clear()
1351     {
1352         if(!numelems) return;
1353         memset(chains, 0, size*sizeof(chain *));
1354         numelems = 0;
1355         unused = NULL;
1356         deletechunks();
1357     }
1358 
enumnexthashbase1359     static inline chain *enumnext(void *i) { return ((chain *)i)->next; }
enumkeyhashbase1360     static inline K &enumkey(void *i) { return H::getkey(((chain *)i)->elem); }
enumdatahashbase1361     static inline T &enumdata(void *i) { return H::getdata(((chain *)i)->elem); }
1362 };
1363 
htrecycle(const T &)1364 template<class T> static inline void htrecycle(const T &) {}
1365 
1366 template<class T> struct hashset : hashbase<hashset<T>, T, T, T>
1367 {
1368     typedef hashbase<hashset<T>, T, T, T> basetype;
1369 
basetypehashset1370     hashset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
1371 
getkeyhashset1372     static inline const T &getkey(const T &elem) { return elem; }
getdatahashset1373     static inline T &getdata(T &elem) { return elem; }
setkeyhashset1374     template<class K> static inline void setkey(T &elem, const K &key) {}
1375 
1376     template<class V>
addhashset1377     T &add(const V &elem)
1378     {
1379         return basetype::access(elem, elem);
1380     }
1381 };
1382 
1383 template<class T> struct hashnameset : hashbase<hashnameset<T>, T, const char *, T>
1384 {
1385     typedef hashbase<hashnameset<T>, T, const char *, T> basetype;
1386 
basetypehashnameset1387     hashnameset(int size = basetype::DEFAULTSIZE) : basetype(size) {}
1388 
getkeyhashnameset1389     template<class U> static inline const char *getkey(const U &elem) { return elem.name; }
getkeyhashnameset1390     template<class U> static inline const char *getkey(U *elem) { return elem->name; }
getdatahashnameset1391     static inline T &getdata(T &elem) { return elem; }
setkeyhashnameset1392     template<class K> static inline void setkey(T &elem, const K &key) {}
1393 
1394     template<class V>
addhashnameset1395     T &add(const V &elem)
1396     {
1397         return basetype::access(getkey(elem), elem);
1398     }
1399 };
1400 
1401 template<class K, class T> struct hashtableentry
1402 {
1403     K key;
1404     T data;
1405 };
1406 
1407 template<class K, class T>
htrecycle(hashtableentry<K,T> & entry)1408 static inline void htrecycle(hashtableentry<K, T> &entry)
1409 {
1410     htrecycle(entry.key);
1411     htrecycle(entry.data);
1412 }
1413 
1414 template<class K, class T> struct hashtable : hashbase<hashtable<K, T>, hashtableentry<K, T>, K, T>
1415 {
1416     typedef hashbase<hashtable<K, T>, hashtableentry<K, T>, K, T> basetype;
1417     typedef typename basetype::elemtype elemtype;
1418 
basetypehashtable1419     hashtable(int size = basetype::DEFAULTSIZE) : basetype(size) {}
1420 
getkeyhashtable1421     static inline K &getkey(elemtype &elem) { return elem.key; }
getdatahashtable1422     static inline T &getdata(elemtype &elem) { return elem.data; }
setkeyhashtable1423     template<class U> static inline void setkey(elemtype &elem, const U &key) { elem.key = key; }
1424 };
1425 
1426 #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { k &e = (ht).enumkey(ec); t &f = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; }
1427 #define enumerate(ht,t,e,b)       loopi((ht).size) for(void *ec = (ht).chains[i]; ec;) { t &e = (ht).enumdata(ec); ec = (ht).enumnext(ec); b; }
1428 
1429 struct unionfind
1430 {
1431     struct ufval
1432     {
1433         int rank, next;
1434 
ufvalunionfind::ufval1435         ufval() : rank(0), next(-1) {}
1436     };
1437 
1438     vector<ufval> ufvals;
1439 
findunionfind1440     int find(int k)
1441     {
1442         if(k>=ufvals.length()) return k;
1443         while(ufvals[k].next>=0) k = ufvals[k].next;
1444         return k;
1445     }
1446 
compressfindunionfind1447     int compressfind(int k)
1448     {
1449         if(ufvals[k].next<0) return k;
1450         return ufvals[k].next = compressfind(ufvals[k].next);
1451     }
1452 
uniteunionfind1453     void unite (int x, int y)
1454     {
1455         while(ufvals.length() <= max(x, y)) ufvals.add();
1456         x = compressfind(x);
1457         y = compressfind(y);
1458         if(x==y) return;
1459         ufval &xval = ufvals[x], &yval = ufvals[y];
1460         if(xval.rank < yval.rank) xval.next = y;
1461         else
1462         {
1463             yval.next = x;
1464             if(xval.rank==yval.rank) yval.rank++;
1465         }
1466     }
1467 };
1468 
1469 template <class T, int SIZE> struct queue
1470 {
1471     int head, tail, len;
1472     T data[SIZE];
1473 
queuequeue1474     queue() { clear(); }
1475 
clearqueue1476     void clear() { head = tail = len = 0; }
1477 
lengthqueue1478     int length() const { return len; }
emptyqueue1479     bool empty() const { return !len; }
fullqueue1480     bool full() const { return len == SIZE; }
1481 
inrangequeue1482     bool inrange(size_t i) const { return i<size_t(len); }
inrangequeue1483     bool inrange(int i) const { return i>=0 && i<len; }
1484 
addedqueue1485     T &added() { return data[tail > 0 ? tail-1 : SIZE-1]; }
addedqueue1486     T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; }
addingqueue1487     T &adding() { return data[tail]; }
addingqueue1488     T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; }
addqueue1489     T &add()
1490     {
1491         T &t = data[tail];
1492         tail++;
1493         if(tail >= SIZE) tail -= SIZE;
1494         if(len < SIZE) len++;
1495         return t;
1496     }
addqueue1497     T &add(const T &e) { return add() = e; }
1498 
insertbackqueue1499     T &insertback(int offset)
1500     {
1501         int cur = tail, next = tail;
1502         add();
1503         loopi(offset)
1504         {
1505             cur--;
1506             if(cur < 0) cur += SIZE;
1507             data[next] = data[cur];
1508             next = cur;
1509         }
1510         return data[cur];
1511     }
insertbackqueue1512     T &insertback(int offset, const T &e) { return insertback(offset) = e; }
1513 
popqueue1514     T &pop()
1515     {
1516         tail--;
1517         if(tail < 0) tail += SIZE;
1518         len--;
1519         return data[tail];
1520     }
1521 
removingqueue1522     T &removing() { return data[head]; }
removingqueue1523     T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; }
removequeue1524     T &remove()
1525     {
1526         T &t = data[head];
1527         head++;
1528         if(head >= SIZE) head -= SIZE;
1529         len--;
1530         return t;
1531     }
1532 
1533     T &operator[](int offset) { return removing(offset); }
1534     const T &operator[](int offset) const { return removing(offset); }
1535 };
1536 
1537 template <class T, int SIZE> struct reversequeue : queue<T, SIZE>
1538 {
insertreversequeue1539     T &insert(int offset) { return queue<T, SIZE>::insertback(offset); }
insertreversequeue1540     T &insert(int offset, const T &e) { return queue<T, SIZE>::insertback(offset, e); }
1541 
1542     T &operator[](int offset) { return queue<T, SIZE>::added(offset); }
1543     const T &operator[](int offset) const { return queue<T, SIZE>::added(offset); }
1544 };
1545 
1546 #if defined(WIN32) && !defined(__GNUC__)
1547 #ifdef _DEBUG
1548 //#define _CRTDBG_MAP_ALLOC
1549 #include <crtdbg.h>
new(size_t n,const char * fn,int l)1550 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)1551 inline void __cdecl operator delete(void *p, const char *fn, int l) { ::operator delete(p, 1, fn, l); }
1552 #define new new(__FILE__,__LINE__)
1553 #endif
1554 #endif
1555 
islittleendian()1556 static inline bool islittleendian() { union { int i; uchar b[sizeof(int)]; } conv; conv.i = 1; return conv.b[0] != 0; }
1557 #ifdef SDL_BYTEORDER
1558 #define endianswap16 SDL_Swap16
1559 #define endianswap32 SDL_Swap32
1560 #define endianswap64 SDL_Swap64
1561 #else
endianswap16(ushort n)1562 inline ushort endianswap16(ushort n) { return (n<<8) | (n>>8); }
endianswap32(uint n)1563 inline uint endianswap32(uint n) { return (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000); }
endianswap64(ullong n)1564 inline ullong endianswap64(ullong n) { return endianswap32(uint(n >> 32)) | ((ullong)endianswap32(uint(n)) << 32); }
1565 #endif
endianswap(T n)1566 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; }
1567 template<> inline ushort endianswap<ushort>(ushort n) { return endianswap16(n); }
1568 template<> inline short endianswap<short>(short n) { return endianswap16(n); }
1569 template<> inline uint endianswap<uint>(uint n) { return endianswap32(n); }
1570 template<> inline int endianswap<int>(int n) { return endianswap32(n); }
1571 template<> inline ullong endianswap<ullong>(ullong n) { return endianswap64(n); }
1572 template<> inline llong endianswap<llong>(llong n) { return endianswap64(n); }
1573 template<> inline double endianswap<double>(double n) { union { double t; uint i; } conv; conv.t = n; conv.i = endianswap64(conv.i); return conv.t; }
endianswap(T * buf,size_t len)1574 template<class T> inline void endianswap(T *buf, size_t len) { for(T *end = &buf[len]; buf < end; buf++) *buf = endianswap(*buf); }
endiansame(T n)1575 template<class T> inline T endiansame(T n) { return n; }
endiansame(T * buf,size_t len)1576 template<class T> inline void endiansame(T *buf, size_t len) {}
1577 #ifdef SDL_BYTEORDER
1578 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1579 #define lilswap endiansame
1580 #define bigswap endianswap
1581 #else
1582 #define lilswap endianswap
1583 #define bigswap endiansame
1584 #endif
1585 #elif defined(__BYTE_ORDER__)
1586 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1587 #define lilswap endiansame
1588 #define bigswap endianswap
1589 #else
1590 #define lilswap endianswap
1591 #define bigswap endiansame
1592 #endif
1593 #else
lilswap(T n)1594 template<class T> inline T lilswap(T n) { return islittleendian() ? n : endianswap(n); }
lilswap(T * buf,size_t len)1595 template<class T> inline void lilswap(T *buf, size_t len) { if(!islittleendian()) endianswap(buf, len); }
bigswap(T n)1596 template<class T> inline T bigswap(T n) { return islittleendian() ? endianswap(n) : n; }
bigswap(T * buf,size_t len)1597 template<class T> inline void bigswap(T *buf, size_t len) { if(islittleendian()) endianswap(buf, len); }
1598 #endif
1599 
1600 /* workaround for some C platforms that have these two functions as macros - not used anywhere */
1601 #ifdef getchar
1602 #undef getchar
1603 #endif
1604 #ifdef putchar
1605 #undef putchar
1606 #endif
1607 
1608 struct stream
1609 {
1610 #ifdef WIN32
1611 #ifdef __GNUC__
1612     typedef off64_t offset;
1613 #else
1614     typedef __int64 offset;
1615 #endif
1616 #else
1617     typedef off_t offset;
1618 #endif
1619 
~streamstream1620     virtual ~stream() {}
1621     virtual void close() = 0;
1622     virtual bool end() = 0;
tellstream1623     virtual offset tell() { return -1; }
rawtellstream1624     virtual offset rawtell() { return tell(); }
1625     virtual bool seek(offset pos, int whence = SEEK_SET) { return false; }
1626     virtual offset size();
rawsizestream1627     virtual offset rawsize() { return size(); }
readstream1628     virtual size_t read(void *buf, size_t len) { return 0; }
writestream1629     virtual size_t write(const void *buf, size_t len) { return 0; }
flushstream1630     virtual bool flush() { return true; }
getcharstream1631     virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; }
putcharstream1632     virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; }
1633     virtual bool getline(char *str, size_t len);
putstringstream1634     virtual bool putstring(const char *str) { size_t len = strlen(str); return write(str, len) == len; }
putlinestream1635     virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); }
1636     virtual size_t printf(const char *fmt, ...) PRINTFARGS(2, 3);
getcrcstream1637     virtual uint getcrc() { return 0; }
1638 
putstream1639     template<class T> size_t put(const T *v, size_t n) { return write(v, n*sizeof(T))/sizeof(T); }
putstream1640     template<class T> bool put(T n) { return write(&n, sizeof(n)) == sizeof(n); }
putlilstream1641     template<class T> bool putlil(T n) { return put<T>(lilswap(n)); }
putbigstream1642     template<class T> bool putbig(T n) { return put<T>(bigswap(n)); }
1643 
getstream1644     template<class T> size_t get(T *v, size_t n) { return read(v, n*sizeof(T))/sizeof(T); }
getstream1645     template<class T> T get() { T n; return read(&n, sizeof(n)) == sizeof(n) ? n : 0; }
getlilstream1646     template<class T> T getlil() { return lilswap(get<T>()); }
getbigstream1647     template<class T> T getbig() { return bigswap(get<T>()); }
1648 
1649 #ifndef STANDALONE
1650     SDL_RWops *rwops();
1651 #endif
1652 };
1653 
1654 template<class T>
1655 struct streambuf
1656 {
1657     stream *s;
1658 
streambufstreambuf1659     streambuf(stream *s) : s(s) {}
1660 
getstreambuf1661     T get() { return s->get<T>(); }
getstreambuf1662     size_t get(T *vals, size_t numvals) { return s->get(vals, numvals); }
putstreambuf1663     void put(const T &val) { s->put(&val, 1); }
putstreambuf1664     void put(const T *vals, size_t numvals) { s->put(vals, numvals); }
lengthstreambuf1665     size_t length() { return s->size(); }
1666 };
1667 
1668 enum
1669 {
1670     CT_PRINT   = 1<<0,
1671     CT_SPACE   = 1<<1,
1672     CT_DIGIT   = 1<<2,
1673     CT_ALPHA   = 1<<3,
1674     CT_LOWER   = 1<<4,
1675     CT_UPPER   = 1<<5,
1676     CT_UNICODE = 1<<6
1677 };
1678 extern const uchar cubectype[256];
iscubeprint(uchar c)1679 static inline int iscubeprint(uchar c) { return cubectype[c]&CT_PRINT; }
iscubespace(uchar c)1680 static inline int iscubespace(uchar c) { return cubectype[c]&CT_SPACE; }
iscubealpha(uchar c)1681 static inline int iscubealpha(uchar c) { return cubectype[c]&CT_ALPHA; }
iscubealnum(uchar c)1682 static inline int iscubealnum(uchar c) { return cubectype[c]&(CT_ALPHA|CT_DIGIT); }
iscubelower(uchar c)1683 static inline int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; }
iscubeupper(uchar c)1684 static inline int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; }
iscubepunct(uchar c)1685 static inline int iscubepunct(uchar c) { return cubectype[c] == CT_PRINT; }
cube2uni(uchar c)1686 static inline int cube2uni(uchar c)
1687 {
1688     extern const int cube2unichars[256];
1689     return cube2unichars[c];
1690 }
uni2cube(int c)1691 static inline uchar uni2cube(int c)
1692 {
1693     extern const int uni2cubeoffsets[8];
1694     extern const uchar uni2cubechars[];
1695     return uint(c) <= 0x7FF ? uni2cubechars[uni2cubeoffsets[c>>8] + (c&0xFF)] : 0;
1696 }
cubelower(uchar c)1697 static inline uchar cubelower(uchar c)
1698 {
1699     extern const uchar cubelowerchars[256];
1700     return cubelowerchars[c];
1701 }
cubeupper(uchar c)1702 static inline uchar cubeupper(uchar c)
1703 {
1704     extern const uchar cubeupperchars[256];
1705     return cubeupperchars[c];
1706 }
1707 extern size_t decodeutf8(uchar *dst, size_t dstlen, const uchar *src, size_t srclen, size_t *carry = NULL);
1708 extern size_t encodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry = NULL);
1709 
1710 extern int crcstream(stream *f);
1711 extern int crcfile(const char *s);
1712 extern char *makerelpath(const char *dir, const char *file, const char *prefix = NULL, const char *cmd = NULL);
1713 extern char *makefile(const char *s, const char *e = "", int revision = 0, int start = 1, bool store = false, bool skip = false);
1714 extern char *path(char *s, bool simple = false);
1715 extern char *copypath(const char *s, bool simple = false);
1716 extern const char *parentdir(const char *directory);
1717 extern bool fileexists(const char *path, const char *mode);
1718 extern bool createdir(const char *path);
1719 extern void sethomedir(const char *dir);
1720 extern void appendhomedir(const char *dir);
1721 extern void addpackagedir(const char *dir, int flags = 0);
1722 extern int maskpackagedirs(int flags);
1723 extern const char *findfile(const char *filename, const char *mode);
1724 extern bool findzipfile(const char *filename);
1725 extern stream *openrawfile(const char *filename, const char *mode);
1726 extern stream *openzipfile(const char *filename, const char *mode);
1727 extern stream *openfile(const char *filename, const char *mode);
1728 extern stream *opentempfile(const char *filename, const char *mode);
1729 extern stream *opengzfile(const char *filename, const char *mode, stream *file = NULL, int level = Z_BEST_COMPRESSION);
1730 extern stream *openutf8file(const char *filename, const char *mode, stream *file = NULL);
1731 extern char *loadstream(stream *f, size_t *size, bool utf8 = true);
1732 extern char *loadfile(const char *fn, size_t *size, bool utf8 = true);
1733 extern bool listdir(const char *dir, bool rel, const char *ext, vector<char *> &files);
1734 extern int listfiles(const char *dir, const char *ext, vector<char *> &files);
1735 extern int listzipfiles(const char *dir, const char *ext, vector<char *> &files);
1736 extern void backup(const char *fname, const char *ext, int revision = 0, int start = 1, bool store = false, bool full = true);
1737 
1738 extern void endianswap(void *, int, int);
1739 extern void seedMT(uint seed);
1740 extern uint randomMT();
1741 extern void putint(ucharbuf &p, int n);
1742 extern void putint(packetbuf &p, int n);
1743 extern void putint(vector<uchar> &p, int n);
1744 extern int getint(ucharbuf &p);
1745 extern void putuint(ucharbuf &p, int n);
1746 extern void putuint(packetbuf &p, int n);
1747 extern void putuint(vector<uchar> &p, int n);
1748 extern int getuint(ucharbuf &p);
1749 extern void putfloat(ucharbuf &p, float f);
1750 extern void putfloat(packetbuf &p, float f);
1751 extern void putfloat(vector<uchar> &p, float f);
1752 extern float getfloat(ucharbuf &p);
1753 extern void sendstring(const char *t, ucharbuf &p);
1754 extern void sendstring(const char *t, packetbuf &p);
1755 extern void sendstring(const char *t, vector<uchar> &p);
1756 extern void getstring(char *t, ucharbuf &p, size_t len);
getstring(char (& t)[N],ucharbuf & p)1757 template<size_t N> static inline void getstring(char (&t)[N], ucharbuf &p) { getstring(t, p, N); }
1758 struct ipmask
1759 {
1760     enet_uint32 ip, mask;
1761 
1762     void parse(const char *name);
1763     int print(char *buf) const;
checkipmask1764     bool check(enet_uint32 host) const { return (host & mask) == ip; }
1765 };
1766 extern char *cubecasestr(const char *str, const char *needle);
1767 extern bool cubematchstr(const char *str, const char *match, bool nocase = false);
1768 extern int cubepattern(const char *str, const char *pattern, bool nocase = false);
1769 #endif
1770