aboutsummaryrefslogtreecommitdiff
path: root/tests/cubescript/tools.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2010-11-13 14:45:22 -0800
committerAlon Zakai <azakai@mozilla.com>2010-11-13 14:45:22 -0800
commit1b153b74662b198f99a1b7e21d8bc60f562f6feb (patch)
treec82af930836346c2da71d62ca10b5db749865e9f /tests/cubescript/tools.h
parentcc66f5d1e8e2aa9c0fc57a78b1b896f0a6cb8581 (diff)
rename sauer to cubescript
--HG-- rename : tests/sauer/README => tests/cubescript/README rename : tests/sauer/command.cpp => tests/cubescript/command.cpp rename : tests/sauer/command.h => tests/cubescript/command.h rename : tests/sauer/tools.h => tests/cubescript/tools.h
Diffstat (limited to 'tests/cubescript/tools.h')
-rw-r--r--tests/cubescript/tools.h878
1 files changed, 878 insertions, 0 deletions
diff --git a/tests/cubescript/tools.h b/tests/cubescript/tools.h
new file mode 100644
index 00000000..08b528e2
--- /dev/null
+++ b/tests/cubescript/tools.h
@@ -0,0 +1,878 @@
+// generic useful stuff for any C++ program
+
+#ifndef _TOOLS_H
+#define _TOOLS_H
+
+#include "emscripten.h" // XXX Emscripten
+
+#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<class T>
+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<class T>
+static inline T max(T a, T b)
+{
+ return a > b ? a : b;
+}
+template<class T>
+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<int(m); v++)
+#define loopi(m) loop(i,m)
+#define loopj(m) loop(j,m)
+#define loopk(m) loop(k,m)
+#define loopl(m) loop(l,m)
+
+
+#define DELETEP(p) if(p) { delete p; p = 0; }
+#define DELETEA(p) if(p) { delete[] p; p = 0; }
+
+#define PI (3.1415927f)
+#define PI2 (2*PI)
+#define SQRT2 (1.4142136f)
+#define SQRT3 (1.7320508f)
+#define RAD (PI / 180.0f)
+
+#ifdef WIN32
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_LN2
+#define M_LN2 0.693147180559945309417
+#endif
+
+#ifndef __GNUC__
+#pragma warning (3: 4189) // local variable is initialized but not referenced
+#pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
+#pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
+#pragma warning (disable: 4355) // 'this' : used in base member initializer list
+#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
+#endif
+
+#define strcasecmp _stricmp
+#define PATHDIV '\\'
+#else
+#define __cdecl
+#define _vsnprintf vsnprintf
+#define PATHDIV '/'
+#endif
+
+// easy safe strings
+
+#define MAXSTRLEN 260
+typedef char string[MAXSTRLEN];
+
+inline void vformatstring(char *d, const char *fmt, va_list v, int len = MAXSTRLEN) { _vsnprintf(d, len, fmt, v); d[len-1] = 0; }
+inline char *copystring(char *d, const char *s, size_t len = MAXSTRLEN) { strncpy(d, s, len); d[len-1] = 0; return d; }
+inline char *concatstring(char *d, const char *s, size_t len = MAXSTRLEN) { size_t used = strlen(d); return used < len ? copystring(d+used, s, len-used) : d; }
+
+struct stringformatter
+{
+ char *buf;
+ stringformatter(char *buf): buf((char *)buf) {}
+ void operator()(const char *fmt, ...)
+ {
+ va_list v;
+ va_start(v, fmt);
+ vformatstring(buf, fmt, v);
+ va_end(v);
+ }
+};
+
+#define formatstring(d) stringformatter((char *)d)
+#define defformatstring(d) string d; formatstring(d)
+#define defvformatstring(d,last,fmt) string d; { va_list ap; va_start(ap, last); vformatstring(d, fmt, ap); va_end(ap); }
+
+#define loopv(v) for(int i = 0; i<(v).length(); i++)
+#define loopvj(v) for(int j = 0; j<(v).length(); j++)
+#define loopvk(v) for(int k = 0; k<(v).length(); k++)
+#define loopvrev(v) for(int i = (v).length()-1; i>=0; i--)
+
+template <class T>
+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<class U>
+ databuf(T *buf, U maxlen) : buf(buf), len(0), maxlen((int)maxlen), flags(0) {}
+
+ const T &get()
+ {
+ static T overreadval;
+ if(len<maxlen) return buf[len++];
+ flags |= OVERREAD;
+ return overreadval;
+ }
+
+ databuf subbuf(int sz)
+ {
+ sz = min(sz, maxlen-len);
+ len += sz;
+ return databuf(&buf[len-sz], sz);
+ }
+
+ void put(const T &val)
+ {
+ if(len<maxlen) buf[len++] = val;
+ else flags |= OVERWROTE;
+ }
+
+ void put(const T *vals, int numvals)
+ {
+ if(maxlen-len<numvals) flags |= OVERWROTE;
+ memcpy(&buf[len], vals, min(maxlen-len, numvals)*ES_SIZEOF(T));
+ len += min(maxlen-len, numvals);
+ }
+
+ int get(T *vals, int numvals)
+ {
+ int read = min(maxlen-len, numvals);
+ if(read<numvals) flags |= OVERREAD;
+ memcpy(vals, &buf[len], read*ES_SIZEOF(T));
+ len += read;
+ return read;
+ }
+
+ int length() const { return len; }
+ int remaining() const { return maxlen-len; }
+ bool overread() const { return (flags&OVERREAD)!=0; }
+ bool overwrote() const { return (flags&OVERWROTE)!=0; }
+
+ void forceoverread()
+ {
+ len = maxlen;
+ flags |= OVERREAD;
+ }
+};
+
+typedef databuf<char> charbuf;
+typedef databuf<uchar> ucharbuf;
+
+template<class T>
+static inline float heapscore(const T &n) { return n; }
+
+template<class T, class U>
+static inline void quicksort(T *buf, int n, int (__cdecl *func)(U *, U *))
+{
+ qsort(buf, n, ES_SIZEOF(T), (int (__cdecl *)(const void *,const void *))func);
+}
+
+template <class T> 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<T> &operator=(const vector<T> &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<T> &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*ES_SIZEOF(T));
+ ulen += v.ulen;
+ v.ulen = 0;
+ }
+ }
+
+ bool inrange(size_t i) const { return i<size_t(ulen); }
+ bool inrange(int i) const { return i>=0 && i<ulen; }
+
+ T &pop() { return buf[--ulen]; }
+ T &last() { return buf[ulen-1]; }
+ void drop() { ulen--; buf[ulen].~T(); }
+ bool empty() const { return ulen==0; }
+
+ int capacity() const { return alen; }
+ int length() const { return ulen; }
+ T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; }
+ const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; }
+
+ void shrink(int i) { ASSERT(i<=ulen); while(ulen>i) 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<class ST>
+ 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*ES_SIZEOF(T)];
+ if(olen > 0)
+ {
+ memcpy(newbuf, buf, olen*ES_SIZEOF(T));
+ delete[] (uchar *)buf;
+ }
+ buf = (T *)newbuf;
+ }
+
+ databuf<T> reserve(int sz)
+ {
+ if(ulen+sz > alen) growbuf(ulen+sz);
+ return databuf<T>(&buf[ulen], sz);
+ }
+
+ void advance(int sz)
+ {
+ ulen += sz;
+ }
+
+ void addbuf(const databuf<T> &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<T> buf = reserve(n);
+ buf.put(v, n);
+ addbuf(buf);
+ }
+
+ void remove(int i, int n)
+ {
+ for(int p = i+n; p<ulen; p++) buf[p-n] = buf[p];
+ ulen -= n;
+ }
+
+ T remove(int i)
+ {
+ T e = buf[i];
+ for(int p = i+1; p<ulen; p++) buf[p-1] = buf[p];
+ ulen--;
+ return e;
+ }
+
+ T removeunordered(int i)
+ {
+ T e = buf[i];
+ ulen--;
+ if(ulen>0) buf[i] = buf[ulen];
+ return e;
+ }
+
+ template<class U>
+ 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<class T> 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<class K>
+ T *access(const K &key)
+ {
+ HTFIND(key, &c->elem, NULL);
+ }
+
+ template<class K>
+ T &access(const K &key, const T &elem)
+ {
+ HTFIND(key, c->elem, insert(h)->elem = elem);
+ }
+
+ template<class K>
+ T &operator[](const K &key)
+ {
+ HTFIND(key, c->elem, insert(h)->elem);
+ }
+
+ template<class K>
+ 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<class K, class T> struct hashtableentry
+{
+ K key;
+ T data;
+
+ hashtableentry() {}
+ hashtableentry(const K &key, const T &data) : key(key), data(data) {}
+};
+
+template<class U, class K, class T>
+static inline bool htcmp(const U *x, const hashtableentry<K, T> &y)
+{
+ return htcmp(x, y.key);
+}
+
+template<class U, class K, class T>
+static inline bool htcmp(const U &x, const hashtableentry<K, T> &y)
+{
+ return htcmp(x, y.key);
+}
+
+template<class K, class T> struct hashtable : hashset<hashtableentry<K, T> >
+{
+ typedef hashtableentry<K, T> entry;
+ typedef struct hashset<entry>::chain chain;
+ typedef K key;
+ typedef T value;
+
+ hashtable(int size = 1<<10) : hashset<entry>(size) {}
+
+ entry &insert(const K &key, uint h)
+ {
+ chain *c = hashset<entry>::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<t>::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<k,t>::chain *enumc = (ht).chains[i]; enumc;) { const hashtable<k,t>::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<ufval> 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 <class T, int SIZE> 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 <class T, int SIZE> 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 <crtdbg.h>
+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<class T> 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>(ushort n) { return endianswap16(n); }
+template<> inline short endianswap<short>(short n) { return endianswap16(n); }
+template<> inline uint endianswap<uint>(uint n) { return endianswap32(n); }
+template<> inline int endianswap<int>(int n) { return endianswap32(n); }
+template<class T> inline void endianswap(T *buf, int len) { for(T *end = &buf[len]; buf < end; buf++) *buf = endianswap(*buf); }
+template<class T> inline T endiansame(T n) { return n; }
+template<class T> 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<class T> inline T lilswap(T n) { return *(const uchar *)&islittleendian ? n : endianswap(n); }
+template<class T> inline void lilswap(T *buf, int len) { if(!*(const uchar *)&islittleendian) endianswap(buf, len); }
+template<class T> inline T bigswap(T n) { return *(const uchar *)&islittleendian ? endianswap(n) : n; }
+template<class T> 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<class T> bool put(T n) { return write(&n, ES_SIZEOV(n)) == ES_SIZEOV(n); }
+ template<class T> bool putlil(T n) { return put<T>(lilswap(n)); }
+ template<class T> bool putbig(T n) { return put<T>(bigswap(n)); }
+
+ template<class T> T get() { T n; return read(&n, ES_SIZEOV(n)) == ES_SIZEOV(n) ? n : 0; }
+ template<class T> T getlil() { return lilswap(get<T>()); }
+ template<class T> T getbig() { return bigswap(get<T>()); }
+};
+
+#endif
+