212 lines
4.7 KiB
C++
212 lines
4.7 KiB
C++
// implementation of generic tools
|
|
|
|
#include "tools.hh"
|
|
|
|
#include <ctime>
|
|
|
|
void *operator new(size_t size)
|
|
{
|
|
void *p = malloc(size);
|
|
if(!p) abort();
|
|
return p;
|
|
}
|
|
|
|
void *operator new[](size_t size)
|
|
{
|
|
void *p = malloc(size);
|
|
if(!p) abort();
|
|
return p;
|
|
}
|
|
|
|
void operator delete(void *p) { if(p) free(p); }
|
|
|
|
void operator delete[](void *p) { if(p) free(p); }
|
|
|
|
void *operator new(size_t size, bool err)
|
|
{
|
|
void *p = malloc(size);
|
|
if(!p && err) abort();
|
|
return p;
|
|
}
|
|
|
|
void *operator new[](size_t size, bool err)
|
|
{
|
|
void *p = malloc(size);
|
|
if(!p && err) abort();
|
|
return p;
|
|
}
|
|
|
|
////////////////////////// strings ////////////////////////////////////////
|
|
|
|
static string tmpstr[4];
|
|
static int tmpidx = 0;
|
|
|
|
char *tempformatstring(const char *fmt, ...)
|
|
{
|
|
tmpidx = (tmpidx+1)%4;
|
|
|
|
va_list v;
|
|
va_start(v, fmt);
|
|
vformatstring(tmpstr[tmpidx], fmt, v);
|
|
va_end(v);
|
|
|
|
return tmpstr[tmpidx];
|
|
}
|
|
|
|
////////////////////////// rnd numbers ////////////////////////////////////////
|
|
|
|
#define N (624)
|
|
#define M (397)
|
|
#define K (0x9908B0DFU)
|
|
|
|
static uint state[N];
|
|
static int next = N;
|
|
|
|
void seedMT(uint seed)
|
|
{
|
|
state[0] = seed;
|
|
for(uint i = 1; i < N; i++)
|
|
state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i;
|
|
next = 0;
|
|
}
|
|
|
|
uint randomMT()
|
|
{
|
|
int cur = next;
|
|
if(++next >= N)
|
|
{
|
|
if(next > N) { seedMT(5489U + time(nullptr)); cur = next++; }
|
|
else next = 0;
|
|
}
|
|
uint y = (state[cur] & 0x80000000U) | (state[next] & 0x7FFFFFFFU);
|
|
state[cur] = y = state[cur < N-M ? cur + M : cur + M-N] ^ (y >> 1) ^ (-int(y & 1U) & K);
|
|
y ^= (y >> 11);
|
|
y ^= (y << 7) & 0x9D2C5680U;
|
|
y ^= (y << 15) & 0xEFC60000U;
|
|
y ^= (y >> 18);
|
|
return y;
|
|
}
|
|
|
|
#undef N
|
|
#undef M
|
|
#undef K
|
|
|
|
///////////////////////// network ///////////////////////
|
|
|
|
// all network traffic is in 32bit ints, which are then compressed using the following simple scheme (assumes that most values are small).
|
|
|
|
template<class T>
|
|
static inline void putint_(T &p, int n)
|
|
{
|
|
if(n<128 && n>-127) p.put(n);
|
|
else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); }
|
|
else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); }
|
|
}
|
|
void putint(ucharbuf &p, int n) { putint_(p, n); }
|
|
void putint(vector<uchar> &p, int n) { putint_(p, n); }
|
|
|
|
int getint(ucharbuf &p)
|
|
{
|
|
int c = (signed char)p.get();
|
|
if(c==-128) { int n = p.get(); n |= ((signed char)p.get())<<8; return n; }
|
|
else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; return n|(p.get()<<24); }
|
|
else return c;
|
|
}
|
|
|
|
// much smaller encoding for unsigned integers up to 28 bits, but can handle signed
|
|
template<class T>
|
|
static inline void putuint_(T &p, int n)
|
|
{
|
|
if(n < 0 || n >= (1<<21))
|
|
{
|
|
p.put(0x80 | (n & 0x7F));
|
|
p.put(0x80 | ((n >> 7) & 0x7F));
|
|
p.put(0x80 | ((n >> 14) & 0x7F));
|
|
p.put(n >> 21);
|
|
}
|
|
else if(n < (1<<7)) p.put(n);
|
|
else if(n < (1<<14))
|
|
{
|
|
p.put(0x80 | (n & 0x7F));
|
|
p.put(n >> 7);
|
|
}
|
|
else
|
|
{
|
|
p.put(0x80 | (n & 0x7F));
|
|
p.put(0x80 | ((n >> 7) & 0x7F));
|
|
p.put(n >> 14);
|
|
}
|
|
}
|
|
void putuint(ucharbuf &p, int n) { putuint_(p, n); }
|
|
void putuint(vector<uchar> &p, int n) { putuint_(p, n); }
|
|
|
|
int getuint(ucharbuf &p)
|
|
{
|
|
int n = p.get();
|
|
if(n & 0x80)
|
|
{
|
|
n += (p.get() << 7) - 0x80;
|
|
if(n & (1<<14)) n += (p.get() << 14) - (1<<14);
|
|
if(n & (1<<21)) n += (p.get() << 21) - (1<<21);
|
|
if(n & (1<<28)) n |= ~0U<<28;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
template<class T>
|
|
static inline void putfloat_(T &p, float f)
|
|
{
|
|
lilswap(&f, 1);
|
|
p.put((uchar *)&f, sizeof(float));
|
|
}
|
|
void putfloat(ucharbuf &p, float f) { putfloat_(p, f); }
|
|
void putfloat(vector<uchar> &p, float f) { putfloat_(p, f); }
|
|
|
|
float getfloat(ucharbuf &p)
|
|
{
|
|
float f;
|
|
p.get((uchar *)&f, sizeof(float));
|
|
return lilswap(f);
|
|
}
|
|
|
|
template<class T>
|
|
static inline void sendstring_(const char *t, T &p)
|
|
{
|
|
while(*t) putint(p, *t++);
|
|
putint(p, 0);
|
|
}
|
|
void sendstring(const char *t, ucharbuf &p) { sendstring_(t, p); }
|
|
void sendstring(const char *t, vector<uchar> &p) { sendstring_(t, p); }
|
|
|
|
void getstring(char *text, ucharbuf &p, size_t len)
|
|
{
|
|
char *t = text;
|
|
do
|
|
{
|
|
if(t>=&text[len]) { text[len-1] = 0; return; }
|
|
if(!p.remaining()) { *t = 0; return; }
|
|
*t = getint(p);
|
|
}
|
|
while(*t++);
|
|
}
|
|
|
|
void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len)
|
|
{
|
|
for(int c = uchar(*src); c; c = uchar(*++src))
|
|
{
|
|
if(c == '\f')
|
|
{
|
|
if(!*++src) break;
|
|
continue;
|
|
}
|
|
if(!iscubeprint(c))
|
|
{
|
|
if(!iscubespace(c) || !whitespace) continue;
|
|
if(forcespace) c = ' ';
|
|
}
|
|
*dst++ = c;
|
|
if(!--len) break;
|
|
}
|
|
*dst = '\0';
|
|
}
|