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 ¬found)
1291 {
1292 HTFIND( , notfound);
1293 }
1294
1295 template<class U>
findhashbase1296 const T &find(const U &key, const T ¬found)
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