// 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 #define swap(t,a,b) { t m=a; a=b; b=m; } #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #define rnd(max) (rand()%(max)) #define rndreset() (srand(1)) #define rndtime() { loopi(lastmillis&0xF) rnd(i+1); } #define detrnd(s, x) ((int)(((((uint)(s))*1103515245+12345)>>16)%(x))) #define loop(v,m) for(int v = 0; v void _swap(T &a, T &b) { T t = a; a = b; b = t; } #define loopv(v) if(false) {} else for(int i = 0; i<(v).length(); i++) #define loopvj(v) if(false) {} else for(int j = 0; j<(v).length(); j++) #define loopvk(v) if(false) {} else for(int k = 0; k<(v).length(); k++) #define loopvrev(v) if(false) {} else for(int i = (v).length()-1; i>=0; i--) #define loopvjrev(v) if(false) {} else for(int j = (v).length()-1; i>=0; i--) template struct databuf { enum { OVERREAD = 1<<0, OVERWROTE = 1<<1 }; T *buf; int len, maxlen; uchar flags; 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 struct vector { T *buf; int alen; int ulen; vector() { alen = 8; buf = (T *)new uchar[alen*sizeof(T)]; ulen = 0; } vector(const vector &v) { alen = v.length(); buf = (T *)new uchar[alen*sizeof(T)]; ulen = 0; *this = v; } ~vector() { setsize(0); delete[] (uchar *)buf; } vector &operator=(const vector &v) { setsize(0); loopv(v) add(v[i]); return *this; } T &add(const T &x) { if(ulen==alen) vrealloc(); new (&buf[ulen]) T(x); return buf[ulen++]; } T &add() { if(ulen==alen) vrealloc(); new (&buf[ulen]) T; return buf[ulen++]; } T &dup() { if(ulen==alen) vrealloc(); new (&buf[ulen]) T(buf[ulen-1]); return buf[ulen++]; } bool inrange(size_t i) const { return i=0 && i=0 && i= 0 && ii) drop(); } void setsizenodelete(int i) { ASSERT(i<=ulen); ulen = i; } void deletecontentsp() { while(!empty()) delete pop(); } void deletecontentsa() { while(!empty()) delete[] pop(); } T *getbuf() { return buf; } const T *getbuf() const { return buf; } template void sort(int (__cdecl *cf)(ST *, ST *), int i = 0, int n = -1) { qsort(&buf[i], n<0?ulen:n, sizeof(T), (int (__cdecl *)(const void *,const void *))cf); } void *_realloc(void *p, int oldsize, int newsize) { void *np = new uchar[newsize]; memcpy(np, p, newsize>oldsize ? oldsize : newsize); delete[] (uchar *)p; return np; } void vrealloc() { int olen = alen; buf = (T *)_realloc(buf, olen*sizeof(T), (alen *= 2)*sizeof(T)); } databuf reserve(int sz) { while(alen-ulen(&buf[ulen], sz); } void addbuf(const databuf &p) { ulen += p.length(); } void remove(int i, int n) { for(int p = i+n; pi; p--) buf[p] = buf[p-1]; buf[i] = e; return buf[i]; } }; typedef vector cvector; typedef vector ivector; typedef vector usvector; 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; } static inline uint hthash(uint key) { return key; } static inline bool htcmp(uint x, uint y) { return x==y; } template struct hashtable { typedef K key; typedef const K const_key; typedef T value; typedef const T const_value; enum { CHUNKSIZE = 16 }; struct chain { T data; K key; chain *next; }; struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; }; int size; int numelems; chain **table; chain *enumc; chainchunk *chunks; chain *unused; hashtable(int size = 1<<10) : size(size) { numelems = 0; chunks = NULL; unused = NULL; table = new chain *[size]; loopi(size) table[i] = NULL; } ~hashtable() { DELETEA(table); } chain *insert(const K &key, 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->key = key; c->next = table[h]; table[h] = c; numelems++; return c; } chain *find(const K &key, bool doinsert) { uint h = hthash(key)&(size-1); for(chain *c = table[h]; c; c = c->next) { if(htcmp(key, c->key)) return c; } if(doinsert) return insert(key, h); return NULL; } T *access(const K &key, const T *data = NULL) { chain *c = find(key, data != NULL); if(data) c->data = *data; if(c) return &c->data; return NULL; } T &operator[](const K &key) { return find(key, true)->data; } bool remove(const K &key) { uint h = hthash(key)&(size-1); for(chain **p = &table[h], *c = table[h]; c; p = &c->next, c = c->next) { if(htcmp(key, c->key)) { *p = c->next; c->data.~T(); c->key.~K(); new (&c->data) T(); new (&c->key) K(); c->next = unused; unused = c->next; numelems--; return true; } } return false; } void clear() { loopi(size) table[i] = NULL; numelems = 0; unused = NULL; for(chainchunk *nextchunk; chunks; chunks = nextchunk) { nextchunk = chunks->next; delete chunks; } } }; #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(hashtable::chain *enumc = (ht).table[i]; enumc; enumc = enumc->next) { hashtable::const_key &e = enumc->key; t &f = enumc->data; b; } #define enumerate(ht,t,e,b) loopi((ht).size) for((ht).enumc = (ht).table[i]; (ht).enumc; (ht).enumc = (ht).enumc->next) { t &e = (ht).enumc->data; b; } #define enumerateht(ht) loopi((ht).size) for((ht).enumc = (ht).table[i]; (ht).enumc; (ht).enumc = (ht).enumc->next) inline char *newstring(size_t l) { return new char[l+1]; } inline char *newstring(const char *s, size_t l) { return s_strncpy(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, _MAXDEFSTR-1); } extern char *path(char *s, bool copy = false); extern const char *parentdir(const char *directory); extern bool fileexists(const char *path, const char *mode); extern bool createdir(const char *path); extern void sethomedir(const char *dir); extern void addpackagedir(const char *dir); extern const char *findfile(const char *filename, const char *mode); extern FILE *openfile(const char *filename, const char *mode); extern gzFile opengzfile(const char *filename, const char *mode); extern char *loadfile(const char *fn, int *size); extern bool listdir(const char *dir, const char *ext, vector &files); extern int listfiles(const char *dir, const char *ext, vector &files); extern bool cmpb(void *b, int n, enet_uint32 c); extern bool cmpf(char *fn, enet_uint32 c); extern void endianswap(void *, int, int); #endif