1 // generic useful stuff for any C++ program
11 typedef unsigned char uchar
;
12 typedef unsigned short ushort
;
13 typedef unsigned int uint
;
17 #define ASSERT(c) if(!(c)) { asm("int $3"); }
19 #define ASSERT(c) if(!(c)) { __asm int 3 }
22 #define ASSERT(c) if(c) {}
29 static inline void swap(T
&a
, T
&b
)
42 static inline T
max(T a
, T b
)
47 static inline T
min(T a
, T b
)
52 #define clamp(a,b,c) (max(b, min(a, c)))
53 #define rnd(x) ((int)(randomMT()&0xFFFFFF)%(x))
54 #define detrnd(s, x) ((int)(((((uint)(s))*1103515245+12345)>>16)%(x)))
56 #define loop(v,m) for(int v = 0; v<int(m); v++)
57 #define loopi(m) loop(i,m)
58 #define loopj(m) loop(j,m)
59 #define loopk(m) loop(k,m)
60 #define loopl(m) loop(l,m)
63 #define DELETEP(p) if(p) { delete p; p = 0; }
64 #define DELETEA(p) if(p) { delete[] p; p = 0; }
66 #define PI (3.1415927f)
68 #define SQRT2 (1.4142136f)
69 #define SQRT3 (1.7320508f)
70 #define RAD (PI / 180.0f)
76 #define M_PI 3.14159265
79 #pragma warning (3: 4189) // local variable is initialized but not referenced
80 #pragma warning (disable: 4244) // conversion from 'int' to 'float', possible loss of data
81 #pragma warning (disable: 4267) // conversion from 'size_t' to 'int', possible loss of data
82 #pragma warning (disable: 4355) // 'this' : used in base member initializer list
83 #pragma warning (disable: 4996) // 'strncpy' was declared deprecated
86 #define strcasecmp _stricmp
90 #define _vsnprintf vsnprintf
97 typedef char string
[MAXSTRLEN
];
99 inline void formatstring(char *d
, const char *fmt
, va_list v
) { _vsnprintf(d
, MAXSTRLEN
, fmt
, v
); d
[MAXSTRLEN
-1] = 0; }
100 inline char *s_strncpy(char *d
, const char *s
, size_t m
) { strncpy(d
,s
,m
); d
[m
-1] = 0; return d
; }
101 inline char *s_strcpy(char *d
, const char *s
) { return s_strncpy(d
,s
,MAXSTRLEN
); }
102 inline char *s_strcat(char *d
, const char *s
) { size_t n
= strlen(d
); return s_strncpy(d
+n
,s
,MAXSTRLEN
-n
); }
108 s_sprintf_f(char *str
): d(str
) {}
109 void operator()(const char* fmt
, ...)
113 formatstring(d
, fmt
, v
);
118 #define s_sprintf(d) s_sprintf_f((char *)d)
119 #define s_sprintfd(d) string d; s_sprintf(d)
120 #define s_sprintfdlv(d,last,fmt) string d; { va_list ap; va_start(ap, last); formatstring(d, fmt, ap); va_end(ap); }
121 #define s_sprintfdv(d,fmt) s_sprintfdlv(d,fmt,fmt)
123 #define loopv(v) if(false) {} else for(int i = 0; i<(v).length(); i++)
124 #define loopvj(v) if(false) {} else for(int j = 0; j<(v).length(); j++)
125 #define loopvk(v) if(false) {} else for(int k = 0; k<(v).length(); k++)
126 #define loopvrev(v) if(false) {} else for(int i = (v).length()-1; i>=0; i--)
142 databuf(T
*buf
, U maxlen
) : buf(buf
), len(0), maxlen((int)maxlen
), flags(0) {}
146 static T overreadval
;
147 if(len
<maxlen
) return buf
[len
++];
152 databuf
subbuf(int sz
)
154 sz
= min(sz
, maxlen
-len
);
156 return databuf(&buf
[len
-sz
], sz
);
159 void put(const T
&val
)
161 if(len
<maxlen
) buf
[len
++] = val
;
162 else flags
|= OVERWROTE
;
165 void put(const T
*vals
, int numvals
)
167 if(maxlen
-len
<numvals
) flags
|= OVERWROTE
;
168 memcpy(&buf
[len
], vals
, min(maxlen
-len
, numvals
)*sizeof(T
));
169 len
+= min(maxlen
-len
, numvals
);
172 int get(T
*vals
, int numvals
)
174 int read
= min(maxlen
-len
, numvals
);
175 if(read
<numvals
) flags
|= OVERREAD
;
176 memcpy(vals
, &buf
[len
], read
*sizeof(T
));
181 int length() const { return len
; }
182 int remaining() const { return maxlen
-len
; }
183 bool overread() const { return flags
&OVERREAD
; }
184 bool overwrote() const { return flags
&OVERWROTE
; }
193 typedef databuf
<char> charbuf
;
194 typedef databuf
<uchar
> ucharbuf
;
196 template <class T
> struct vector
198 static const int MINSIZE
= 8;
203 vector() : buf(NULL
), alen(0), ulen(0)
207 vector(const vector
&v
) : buf(NULL
), alen(0), ulen(0)
212 ~vector() { setsize(0); if(buf
) delete[] (uchar
*)buf
; }
214 vector
<T
> &operator=(const vector
<T
> &v
)
217 if(v
.length() > alen
) vrealloc(v
.length());
224 if(ulen
==alen
) vrealloc(ulen
+1);
225 new (&buf
[ulen
]) T(x
);
231 if(ulen
==alen
) vrealloc(ulen
+1);
238 if(ulen
==alen
) vrealloc(ulen
+1);
239 new (&buf
[ulen
]) T(buf
[ulen
-1]);
243 void move(vector
<T
> &v
)
253 vrealloc(ulen
+v
.ulen
);
254 if(v
.ulen
) memcpy(&buf
[ulen
], v
.buf
, v
.ulen
*sizeof(T
));
260 bool inrange(size_t i
) const { return i
<size_t(ulen
); }
261 bool inrange(int i
) const { return i
>=0 && i
<ulen
; }
263 T
&pop() { return buf
[--ulen
]; }
264 T
&last() { return buf
[ulen
-1]; }
265 void drop() { buf
[--ulen
].~T(); }
266 bool empty() const { return ulen
==0; }
268 int length() const { return ulen
; }
269 T
&operator[](int i
) { ASSERT(i
>=0 && i
<ulen
); return buf
[i
]; }
270 const T
&operator[](int i
) const { ASSERT(i
>= 0 && i
<ulen
); return buf
[i
]; }
272 void setsize(int i
) { ASSERT(i
<=ulen
); while(ulen
>i
) drop(); }
273 void setsizenodelete(int i
) { ASSERT(i
<=ulen
); ulen
= i
; }
275 void deletecontentsp() { while(!empty()) delete pop(); }
276 void deletecontentsa() { while(!empty()) delete[] pop(); }
278 T
*getbuf() { return buf
; }
279 const T
*getbuf() const { return buf
; }
282 void sort(int (__cdecl
*cf
)(ST
*, ST
*), int i
= 0, int n
= -1)
284 qsort(&buf
[i
], n
<0 ? ulen
: n
, sizeof(T
), (int (__cdecl
*)(const void *,const void *))cf
);
287 void vrealloc(int sz
)
290 if(!alen
) alen
= max(MINSIZE
, sz
);
291 else while(alen
< sz
) alen
*= 2;
292 if(alen
<= olen
) return;
293 uchar
*newbuf
= new uchar
[alen
*sizeof(T
)];
296 memcpy(newbuf
, buf
, olen
*sizeof(T
));
297 delete[] (uchar
*)buf
;
302 databuf
<T
> reserve(int sz
)
304 if(ulen
+sz
> alen
) vrealloc(ulen
+sz
);
305 return databuf
<T
>(&buf
[ulen
], sz
);
313 void addbuf(const databuf
<T
> &p
)
318 void put(const T
*v
, int n
)
320 databuf
<T
> buf
= reserve(n
);
325 void remove(int i
, int n
)
327 for(int p
= i
+n
; p
<ulen
; p
++) buf
[p
-n
] = buf
[p
];
334 for(int p
= i
+1; p
<ulen
; p
++) buf
[p
-1] = buf
[p
];
342 loopi(ulen
) if(buf
[i
]==o
) return i
;
346 void removeobj(const T
&o
)
348 loopi(ulen
) if(buf
[i
]==o
) remove(i
--);
351 void replacewithlast(const T
&o
)
354 loopi(ulen
-1) if(buf
[i
]==o
)
356 buf
[i
] = buf
[ulen
-1];
361 T
&insert(int i
, const T
&e
)
364 for(int p
= ulen
-1; p
>i
; p
--) buf
[p
] = buf
[p
-1];
369 T
*insert(int i
, const T
*e
, int n
)
371 if(ulen
+n
>alen
) vrealloc(ulen
+n
);
373 for(int p
= ulen
-1; p
>=i
+n
; p
--) buf
[p
] = buf
[p
-n
];
374 loopj(n
) buf
[i
+j
] = e
[j
];
380 loopi(ulen
/2) swap(buf
[i
], buf
[ulen
-1-i
]);
384 typedef vector
<char *> cvector
;
385 typedef vector
<int> ivector
;
386 typedef vector
<ushort
> usvector
;
388 static inline uint
hthash(const char *key
)
391 for(int i
= 0, k
; (k
= key
[i
]); i
++) h
= ((h
<<5)+h
)^k
; // bernstein k=33 xor
395 static inline bool htcmp(const char *x
, const char *y
)
397 return !strcmp(x
, y
);
400 static inline uint
hthash(int key
)
405 static inline bool htcmp(int x
, int y
)
410 template <class K
, class T
> struct hashtable
413 typedef const K const_key
;
415 typedef const T const_value
;
417 enum { CHUNKSIZE
= 64 };
419 struct chain
{ T data
; K key
; chain
*next
; };
420 struct chainchunk
{ chain chains
[CHUNKSIZE
]; chainchunk
*next
; };
430 hashtable(int size
= 1<<10)
436 table
= new chain
*[size
];
437 loopi(size
) table
[i
] = NULL
;
445 chain
*insert(const K
&key
, uint h
)
449 chainchunk
*chunk
= new chainchunk
;
450 chunk
->next
= chunks
;
452 loopi(CHUNKSIZE
-1) chunk
->chains
[i
].next
= &chunk
->chains
[i
+1];
453 chunk
->chains
[CHUNKSIZE
-1].next
= unused
;
454 unused
= chunk
->chains
;
457 unused
= unused
->next
;
465 chain
*find(const K
&key
, bool doinsert
)
467 uint h
= hthash(key
)&(size
-1);
468 for(chain
*c
= table
[h
]; c
; c
= c
->next
)
470 if(htcmp(key
, c
->key
)) return c
;
472 if(doinsert
) return insert(key
, h
);
476 T
*access(const K
&key
, const T
*data
= NULL
)
478 chain
*c
= find(key
, data
!= NULL
);
479 if(data
) c
->data
= *data
;
480 if(c
) return &c
->data
;
484 T
&operator[](const K
&key
)
486 return find(key
, true)->data
;
489 bool remove(const K
&key
)
491 uint h
= hthash(key
)&(size
-1);
492 for(chain
**p
= &table
[h
], *c
= table
[h
]; c
; p
= &c
->next
, c
= c
->next
)
494 if(htcmp(key
, c
->key
))
512 if(!numelems
) return;
513 loopi(size
) table
[i
] = NULL
;
516 for(chainchunk
*nextchunk
; chunks
; chunks
= nextchunk
)
518 nextchunk
= chunks
->next
;
524 #define enumeratekt(ht,k,e,t,f,b) loopi((ht).size) for(hashtable<k,t>::chain *enumc = (ht).table[i]; enumc; enumc = enumc->next) { hashtable<k,t>::const_key &e = enumc->key; t &f = enumc->data; b; }
525 #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; }
533 ufval() : rank(0), next(-1) {}
536 vector
<ufval
> ufvals
;
540 if(k
>=ufvals
.length()) return k
;
541 while(ufvals
[k
].next
>=0) k
= ufvals
[k
].next
;
545 int compressfind(int k
)
547 if(ufvals
[k
].next
<0) return k
;
548 return ufvals
[k
].next
= compressfind(ufvals
[k
].next
);
551 void unite (int x
, int y
)
553 while(ufvals
.length() <= max(x
, y
)) ufvals
.add();
557 ufval
&xval
= ufvals
[x
], &yval
= ufvals
[y
];
558 if(xval
.rank
< yval
.rank
) xval
.next
= y
;
562 if(xval
.rank
==yval
.rank
) yval
.rank
++;
567 template <class T
, int SIZE
> struct ringbuf
572 ringbuf() { clear(); }
579 bool empty() const { return !len
; }
581 const int length() const { return len
; }
588 if(index
>=SIZE
) index
= 0;
593 T
&add() { return add(T()); }
597 int start
= index
- len
;
598 if(start
< 0) start
+= SIZE
;
600 if(i
>= SIZE
) i
-= SIZE
;
604 const T
&operator[](int i
) const
606 int start
= index
- len
;
607 if(start
< 0) start
+= SIZE
;
609 if(i
>= SIZE
) i
-= SIZE
;
614 inline char *newstring(size_t l
) { return new char[l
+1]; }
615 inline char *newstring(const char *s
, size_t l
) { return s_strncpy(newstring(l
), s
, l
+1); }
616 inline char *newstring(const char *s
) { return newstring(s
, strlen(s
)); }
617 inline char *newstringbuf(const char *s
) { return newstring(s
, MAXSTRLEN
-1); }
619 #if defined(WIN32) && !defined(__GNUC__)
621 //#define _CRTDBG_MAP_ALLOC
623 inline void *__cdecl
operator new(size_t n
, const char *fn
, int l
) { return ::operator new(n
, 1, fn
, l
); }
624 inline void __cdecl
operator delete(void *p
, const char *fn
, int l
) { ::operator delete(p
, 1, fn
, l
); }
625 #define new new(__FILE__,__LINE__)
629 extern char *makerelpath(const char *dir
, const char *file
, const char *prefix
= NULL
);
630 extern char *path(char *s
);
631 extern char *path(const char *s
, bool copy
);
632 extern const char *parentdir(const char *directory
);
633 extern bool fileexists(const char *path
, const char *mode
);
634 extern bool createdir(const char *path
);
635 extern void sethomedir(const char *dir
);
636 extern void addpackagedir(const char *dir
);
637 extern const char *findfile(const char *filename
, const char *mode
);
638 extern FILE *openfile(const char *filename
, const char *mode
);
639 extern gzFile
opengzfile(const char *filename
, const char *mode
);
640 extern char *loadfile(const char *fn
, int *size
);
641 extern bool listdir(const char *dir
, const char *ext
, vector
<char *> &files
);
642 extern int listfiles(const char *dir
, const char *ext
, vector
<char *> &files
);
643 extern void endianswap(void *, int, int);
644 extern void seedMT(uint seed
);
645 extern uint
randomMT(void);