// generic useful stuff for any C++ program #ifndef _TOOLS_H #define _TOOLS_H #ifdef NULL #undef NULL #endif #define NULL 0 typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; #ifdef _DEBUG #ifdef __GNUC__ #define ASSERT(c) if(!(c)) { asm("int $3"); } #else #define ASSERT(c) if(!(c)) { __asm int 3 } #endif #else #define ASSERT(c) if(c) {} #endif #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400) #define RESTRICT __restrict #else #define RESTRICT #endif #ifdef swap #undef swap #endif template static inline void swap(T &a, T &b) { T t = a; a = b; b = t; } #ifdef max #undef max #endif #ifdef min #undef min #endif template static inline T max(T a, T b) { return a > b ? a : b; } template static inline T min(T a, T b) { return a < b ? a : b; } #define clamp(a,b,c) (max(b, min(a, c))) #define rnd(x) ((int)(randomMT()&0xFFFFFF)%(x)) #define rndscale(x) (float((randomMT()&0xFFFFFF)*double(x)/double(0xFFFFFF))) #define detrnd(s, x) ((int)(((((uint)(s))*1103515245+12345)>>16)%(x))) #define loop(v,m) for(int v = 0; v=0; i--) template struct databuf { enum { OVERREAD = 1<<0, OVERWROTE = 1<<1 }; T *buf; int len, maxlen; uchar flags; databuf() : buf(NULL), len(0), maxlen(0), flags(0) {} template databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {} const T &get() { static T overreadval; if(len charbuf; typedef databuf ucharbuf; template static inline float heapscore(const T &n) { return n; } template static inline void quicksort(T *buf, int n, int (__cdecl *func)(U *, U *)) { qsort(buf, n, sizeof(T), (int (__cdecl *)(const void *,const void *))func); } template struct vector { static const int MINSIZE = 8; T *buf; int alen, ulen; vector() : buf(NULL), alen(0), ulen(0) { } vector(const vector &v) : buf(NULL), alen(0), ulen(0) { *this = v; } ~vector() { shrink(0); if(buf) delete[] (uchar *)buf; } vector &operator=(const vector &v) { shrink(0); if(v.length() > alen) growbuf(v.length()); loopv(v) add(v[i]); return *this; } T &add(const T &x) { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T(x); return buf[ulen++]; } T &add() { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T; return buf[ulen++]; } T &dup() { if(ulen==alen) growbuf(ulen+1); new (&buf[ulen]) T(buf[ulen-1]); return buf[ulen++]; } void move(vector &v) { if(!ulen) { swap(buf, v.buf); swap(ulen, v.ulen); swap(alen, v.alen); } else { growbuf(ulen+v.ulen); if(v.ulen) memcpy(&buf[ulen], v.buf, v.ulen*sizeof(T)); ulen += v.ulen; v.ulen = 0; } } bool inrange(size_t i) const { return i=0 && i=0 && i= 0 && ii) drop(); } void setsize(int i) { ASSERT(i<=ulen); ulen = i; } void deletecontents() { while(!empty()) delete pop(); } void deletearrays() { while(!empty()) delete[] pop(); } T *getbuf() { return buf; } const T *getbuf() const { return buf; } bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; } template void sort(int (__cdecl *cf)(ST *, ST *), int i = 0, int n = -1) { quicksort(&buf[i], n < 0 ? ulen : n, cf); } void growbuf(int sz) { int olen = alen; if(!alen) alen = max(MINSIZE, sz); else while(alen < sz) alen *= 2; if(alen <= olen) return; uchar *newbuf = new uchar[alen*sizeof(T)]; if(olen > 0) { memcpy(newbuf, buf, olen*sizeof(T)); delete[] (uchar *)buf; } buf = (T *)newbuf; } databuf reserve(int sz) { if(ulen+sz > alen) growbuf(ulen+sz); return databuf(&buf[ulen], sz); } void advance(int sz) { ulen += sz; } void addbuf(const databuf &p) { advance(p.length()); } T *pad(int n) { T *buf = reserve(n).buf; advance(n); return buf; } void put(const T &v) { add(v); } void put(const T *v, int n) { databuf buf = reserve(n); buf.put(v, n); addbuf(buf); } void remove(int i, int n) { for(int p = i+n; p0) buf[i] = buf[ulen]; return e; } template int find(const U &o) { loopi(ulen) if(buf[i]==o) return i; return -1; } void removeobj(const T &o) { loopi(ulen) if(buf[i]==o) remove(i--); } void replacewithlast(const T &o) { if(!ulen) return; loopi(ulen-1) if(buf[i]==o) { buf[i] = buf[ulen-1]; } ulen--; } T &insert(int i, const T &e) { add(T()); for(int p = ulen-1; p>i; p--) buf[p] = buf[p-1]; buf[i] = e; return buf[i]; } T *insert(int i, const T *e, int n) { if(ulen+n>alen) growbuf(ulen+n); loopj(n) add(T()); for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n]; loopj(n) buf[i+j] = e[j]; return &buf[i]; } void reverse() { loopi(ulen/2) swap(buf[i], buf[ulen-1-i]); } static int heapparent(int i) { return (i - 1) >> 1; } static int heapchild(int i) { return (i << 1) + 1; } void buildheap() { for(int i = ulen/2; i >= 0; i--) downheap(i); } int upheap(int i) { float score = heapscore(buf[i]); while(i > 0) { int pi = heapparent(i); if(score >= heapscore(buf[pi])) break; swap(buf[i], buf[pi]); i = pi; } return i; } T &addheap(const T &x) { add(x); return buf[upheap(ulen-1)]; } int downheap(int i) { float score = heapscore(buf[i]); for(;;) { int ci = heapchild(i); if(ci >= ulen) break; float cscore = heapscore(buf[ci]); if(score > cscore) { if(ci+1 < ulen && heapscore(buf[ci+1]) < cscore) { swap(buf[ci+1], buf[i]); i = ci+1; } else { swap(buf[ci], buf[i]); i = ci; } } else if(ci+1 < ulen && heapscore(buf[ci+1]) < score) { swap(buf[ci+1], buf[i]); i = ci+1; } else break; } return i; } T removeheap() { T e = removeunordered(0); if(ulen) downheap(0); return e; } }; static inline uint hthash(const char *key) { uint h = 5381; for(int i = 0, k; (k = key[i]); i++) h = ((h<<5)+h)^k; // bernstein k=33 xor return h; } static inline bool htcmp(const char *x, const char *y) { return !strcmp(x, y); } static inline uint hthash(int key) { return key; } static inline bool htcmp(int x, int y) { return x==y; } template struct hashset { typedef T elem; typedef const T const_elem; enum { CHUNKSIZE = 64 }; struct chain { T elem; chain *next; }; struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; }; int size; int numelems; chain **chains; chainchunk *chunks; chain *unused; hashset(int size = 1<<10) : size(size) { numelems = 0; chunks = NULL; unused = NULL; chains = new chain *[size]; loopi(size) chains[i] = NULL; } ~hashset() { DELETEA(chains); deletechunks(); } chain *insert(uint h) { if(!unused) { chainchunk *chunk = new chainchunk; chunk->next = chunks; chunks = chunk; loopi(CHUNKSIZE-1) chunk->chains[i].next = &chunk->chains[i+1]; chunk->chains[CHUNKSIZE-1].next = unused; unused = chunk->chains; } chain *c = unused; unused = unused->next; c->next = chains[h]; chains[h] = c; numelems++; return c; } #define HTFIND(key, success, fail) \ uint h = hthash(key)&(this->size-1); \ for(chain *c = this->chains[h]; c; c = c->next) \ { \ if(htcmp(key, c->elem)) return (success); \ } \ return (fail); template T *access(const K &key) { HTFIND(key, &c->elem, NULL); } template T &access(const K &key, const T &elem) { HTFIND(key, c->elem, insert(h)->elem = elem); } template T &operator[](const K &key) { HTFIND(key, c->elem, insert(h)->elem); } template bool remove(const K &key) { uint h = hthash(key)&(size-1); for(chain **p = &chains[h], *c = chains[h]; c; p = &c->next, c = c->next) { if(htcmp(key, c->elem)) { *p = c->next; c->elem.~T(); new (&c->elem) T; c->next = unused; unused = c; numelems--; return true; } } return false; } void deletechunks() { for(chainchunk *nextchunk; chunks; chunks = nextchunk) { nextchunk = chunks->next; delete chunks; } } void clear() { if(!numelems) return; loopi(size) chains[i] = NULL; numelems = 0; unused = NULL; deletechunks(); } static inline chain *getnext(void *i) { return ((chain *)i)->next; } static inline T &getdata(void *i) { return ((chain *)i)->elem; } }; template struct hashtableentry { K key; T data; hashtableentry() {} hashtableentry(const K &key, const T &data) : key(key), data(data) {} }; template static inline bool htcmp(const U *x, const hashtableentry &y) { return htcmp(x, y.key); } template static inline bool htcmp(const U &x, const hashtableentry &y) { return htcmp(x, y.key); } template struct hashtable : hashset > { typedef hashtableentry entry; typedef struct hashset::chain chain; typedef K key; typedef T value; hashtable(int size = 1<<10) : hashset(size) {} entry &insert(const K &key, uint h) { chain *c = hashset::insert(h); c->elem.key = key; return c->elem; } T *access(const K &key) { HTFIND(key, &c->elem.data, NULL); } T &access(const K &key, const T &data) { HTFIND(key, c->elem.data, insert(key, h).data = data); } T &operator[](const K &key) { HTFIND(key, c->elem.data, insert(key, h).data); } static inline chain *getnext(void *i) { return ((chain *)i)->next; } static inline K &getkey(void *i) { return ((chain *)i)->elem.key; } static inline T &getdata(void *i) { return ((chain *)i)->elem.data; } }; #define enumerates(ht,t,e,b) loopi((ht).size) for(hashset::chain *enumc = (ht).chains[i]; enumc;) { t &e = enumc->elem; enumc = enumc->next; b; } #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(hashtable::chain *enumc = (ht).chains[i]; enumc;) { const hashtable::key &e = enumc->elem.key; t &f = enumc->elem.data; enumc = enumc->next; b; } #define enumerate(ht,t,e,b) loopi((ht).size) for(void *enumc = (ht).chains[i]; enumc;) { t &e = (ht).getdata(enumc); enumc = (ht).getnext(enumc); b; } struct unionfind { struct ufval { int rank, next; ufval() : rank(0), next(-1) {} }; vector ufvals; int find(int k) { if(k>=ufvals.length()) return k; while(ufvals[k].next>=0) k = ufvals[k].next; return k; } int compressfind(int k) { if(ufvals[k].next<0) return k; return ufvals[k].next = compressfind(ufvals[k].next); } void unite (int x, int y) { while(ufvals.length() <= max(x, y)) ufvals.add(); x = compressfind(x); y = compressfind(y); if(x==y) return; ufval &xval = ufvals[x], &yval = ufvals[y]; if(xval.rank < yval.rank) xval.next = y; else { yval.next = x; if(xval.rank==yval.rank) yval.rank++; } } }; template struct ringbuf { int index, len; T data[SIZE]; ringbuf() { clear(); } void clear() { index = len = 0; } bool empty() const { return !len; } const int length() const { return len; } T &add(const T &e) { T &t = (data[index] = e); index++; if(index >= SIZE) index -= SIZE; if(len < SIZE) len++; return t; } T &add() { return add(T()); } T &operator[](int i) { i += index - len; return data[i < 0 ? i + SIZE : i%SIZE]; } const T &operator[](int i) const { i += index - len; return data[i < 0 ? i + SIZE : i%SIZE]; } }; template struct queue { int head, tail, len; T data[SIZE]; queue() { clear(); } void clear() { head = tail = len = 0; } int length() const { return len; } bool empty() const { return !len; } bool full() const { return len == SIZE; } T &added() { return data[tail > 0 ? tail-1 : SIZE-1]; } T &added(int offset) { return data[tail-offset > 0 ? tail-offset-1 : tail-offset-1 + SIZE]; } T &adding() { return data[tail]; } T &adding(int offset) { return data[tail+offset >= SIZE ? tail+offset - SIZE : tail+offset]; } T &add() { ASSERT(len < SIZE); T &t = data[tail]; tail = (tail + 1)%SIZE; len++; return t; } T &removing() { return data[head]; } T &removing(int offset) { return data[head+offset >= SIZE ? head+offset - SIZE : head+offset]; } T &remove() { ASSERT(len > 0); T &t = data[head]; head = (head + 1)%SIZE; len--; return t; } }; inline char *newstring(size_t l) { return new char[l+1]; } inline char *newstring(const char *s, size_t l) { return copystring(newstring(l), s, l+1); } inline char *newstring(const char *s) { return newstring(s, strlen(s)); } inline char *newstringbuf(const char *s) { return newstring(s, MAXSTRLEN-1); } #if defined(WIN32) && !defined(__GNUC__) #ifdef _DEBUG //#define _CRTDBG_MAP_ALLOC #include inline void *__cdecl operator new(size_t n, const char *fn, int l) { return ::operator new(n, 1, fn, l); } inline void __cdecl operator delete(void *p, const char *fn, int l) { ::operator delete(p, 1, fn, l); } #define new new(__FILE__,__LINE__) #endif #endif const int islittleendian = 1; #ifdef SDL_BYTEORDER #define endianswap16 SDL_Swap16 #define endianswap32 SDL_Swap32 #else inline ushort endianswap16(ushort n) { return (n<<8) | (n>>8); } inline uint endianswap32(uint n) { return (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000); } #endif template inline T endianswap(T n) { union { T t; uint i; } conv; conv.t = n; conv.i = endianswap32(conv.i); return conv.t; } template<> inline ushort endianswap(ushort n) { return endianswap16(n); } template<> inline short endianswap(short n) { return endianswap16(n); } template<> inline uint endianswap(uint n) { return endianswap32(n); } template<> inline int endianswap(int n) { return endianswap32(n); } template inline void endianswap(T *buf, int len) { for(T *end = &buf[len]; buf < end; buf++) *buf = endianswap(*buf); } template inline T endiansame(T n) { return n; } template inline void endiansame(T *buf, int len) {} #ifdef SDL_BYTEORDER #if SDL_BYTEORDER == SDL_LIL_ENDIAN #define lilswap endiansame #define bigswap endianswap #else #define lilswap endianswap #define bigswap endiansame #endif #else template inline T lilswap(T n) { return *(const uchar *)&islittleendian ? n : endianswap(n); } template inline void lilswap(T *buf, int len) { if(!*(const uchar *)&islittleendian) endianswap(buf, len); } template inline T bigswap(T n) { return *(const uchar *)&islittleendian ? endianswap(n) : n; } template inline void bigswap(T *buf, int len) { if(*(const uchar *)&islittleendian) endianswap(buf, len); } #endif /* workaround for some C platforms that have these two functions as macros - not used anywhere */ #ifdef getchar #undef getchar #endif #ifdef putchar #undef putchar #endif struct stream { virtual ~stream() {} virtual void close() = 0; virtual bool end() = 0; virtual long tell() { return -1; } virtual bool seek(long offset, int whence = SEEK_SET) { return false; } virtual long size(); virtual int read(void *buf, int len) { return 0; } virtual int write(const void *buf, int len) { return 0; } virtual int getchar() { uchar c; return read(&c, 1) == 1 ? c : -1; } virtual bool putchar(int n) { uchar c = n; return write(&c, 1) == 1; } virtual bool getline(char *str, int len); virtual bool putstring(const char *str) { int len = (int)strlen(str); return write(str, len) == len; } virtual bool putline(const char *str) { return putstring(str) && putchar('\n'); } virtual int printf(const char *fmt, ...) { return -1; } virtual uint getcrc() { return 0; } template bool put(T n) { return write(&n, ES_SIZEOV(n)) == ES_SIZEOV(n); } template bool putlil(T n) { return put(lilswap(n)); } template bool putbig(T n) { return put(bigswap(n)); } template T get() { T n; return read(&n, ES_SIZEOV(n)) == ES_SIZEOV(n) ? n : 0; } template T getlil() { return lilswap(get()); } template T getbig() { return bigswap(get()); } }; #endif