1 // implementation of generic tools
2 
3 #include "cube.h"
4 
operator new(size_t size)5 void *operator new(size_t size)
6 {
7     void *p = malloc(size);
8     if(!p) abort();
9     return p;
10 }
11 
operator new[](size_t size)12 void *operator new[](size_t size)
13 {
14     void *p = malloc(size);
15     if(!p) abort();
16     return p;
17 }
18 
operator delete(void * p)19 void operator delete(void *p) { if(p) free(p); }
20 
operator delete[](void * p)21 void operator delete[](void *p) { if(p) free(p); }
22 
23 ////////////////////////// strings ////////////////////////////////////////
24 
25 static string tmpstr[4];
26 static int tmpidx = 0;
27 
tempformatstring(const char * fmt,...)28 char *tempformatstring(const char *fmt, ...)
29 {
30     tmpidx = (tmpidx+1)%4;
31     char *buf = tmpstr[tmpidx];
32 
33     va_list v;
34     va_start(v, fmt);
35     vformatstring(buf, fmt, v);
36     va_end(v);
37 
38     return buf;
39 }
40 
41 ////////////////////////// rnd numbers ////////////////////////////////////////
42 
43 #define N (624)
44 #define M (397)
45 #define K (0x9908B0DFU)
46 
47 static uint state[N];
48 static int next = N;
49 
seedMT(uint seed)50 void seedMT(uint seed)
51 {
52     state[0] = seed;
53     for(uint i = 1; i < N; i++)
54         state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i;
55     next = 0;
56 }
57 
randomMT()58 uint randomMT()
59 {
60     int cur = next;
61     if(++next >= N)
62     {
63         if(next > N) { seedMT(5489U + time(NULL)); cur = next++; }
64         else next = 0;
65     }
66     uint y = (state[cur] & 0x80000000U) | (state[next] & 0x7FFFFFFFU);
67     state[cur] = y = state[cur < N-M ? cur + M : cur + M-N] ^ (y >> 1) ^ (-int(y & 1U) & K);
68     y ^= (y >> 11);
69     y ^= (y <<  7) & 0x9D2C5680U;
70     y ^= (y << 15) & 0xEFC60000U;
71     y ^= (y >> 18);
72     return y;
73 }
74 
75 #undef N
76 #undef M
77 #undef K
78 
79 ///////////////////////// network ///////////////////////
80 
81 // all network traffic is in 32bit ints, which are then compressed using the following simple scheme (assumes that most values are small).
82 
83 template<class T>
putint_(T & p,int n)84 static inline void putint_(T &p, int n)
85 {
86     if(n<128 && n>-127) p.put(n);
87     else if(n<0x8000 && n>=-0x8000) { p.put(0x80); p.put(n); p.put(n>>8); }
88     else { p.put(0x81); p.put(n); p.put(n>>8); p.put(n>>16); p.put(n>>24); }
89 }
putint(ucharbuf & p,int n)90 void putint(ucharbuf &p, int n) { putint_(p, n); }
putint(packetbuf & p,int n)91 void putint(packetbuf &p, int n) { putint_(p, n); }
putint(vector<uchar> & p,int n)92 void putint(vector<uchar> &p, int n) { putint_(p, n); }
93 
getint(ucharbuf & p)94 int getint(ucharbuf &p)
95 {
96     int c = (char)p.get();
97     if(c==-128) { int n = p.get(); n |= char(p.get())<<8; return n; }
98     else if(c==-127) { int n = p.get(); n |= p.get()<<8; n |= p.get()<<16; return n|(p.get()<<24); }
99     else return c;
100 }
101 
102 // much smaller encoding for unsigned integers up to 28 bits, but can handle signed
103 template<class T>
putuint_(T & p,int n)104 static inline void putuint_(T &p, int n)
105 {
106     if(n < 0 || n >= (1<<21))
107     {
108         p.put(0x80 | (n & 0x7F));
109         p.put(0x80 | ((n >> 7) & 0x7F));
110         p.put(0x80 | ((n >> 14) & 0x7F));
111         p.put(n >> 21);
112     }
113     else if(n < (1<<7)) p.put(n);
114     else if(n < (1<<14))
115     {
116         p.put(0x80 | (n & 0x7F));
117         p.put(n >> 7);
118     }
119     else
120     {
121         p.put(0x80 | (n & 0x7F));
122         p.put(0x80 | ((n >> 7) & 0x7F));
123         p.put(n >> 14);
124     }
125 }
putuint(ucharbuf & p,int n)126 void putuint(ucharbuf &p, int n) { putuint_(p, n); }
putuint(packetbuf & p,int n)127 void putuint(packetbuf &p, int n) { putuint_(p, n); }
putuint(vector<uchar> & p,int n)128 void putuint(vector<uchar> &p, int n) { putuint_(p, n); }
129 
getuint(ucharbuf & p)130 int getuint(ucharbuf &p)
131 {
132     int n = p.get();
133     if(n & 0x80)
134     {
135         n += (p.get() << 7) - 0x80;
136         if(n & (1<<14)) n += (p.get() << 14) - (1<<14);
137         if(n & (1<<21)) n += (p.get() << 21) - (1<<21);
138         if(n & (1<<28)) n |= -1<<28;
139     }
140     return n;
141 }
142 
143 template<class T>
putfloat_(T & p,float f)144 static inline void putfloat_(T &p, float f)
145 {
146     lilswap(&f, 1);
147     p.put((uchar *)&f, sizeof(float));
148 }
putfloat(ucharbuf & p,float f)149 void putfloat(ucharbuf &p, float f) { putfloat_(p, f); }
putfloat(packetbuf & p,float f)150 void putfloat(packetbuf &p, float f) { putfloat_(p, f); }
putfloat(vector<uchar> & p,float f)151 void putfloat(vector<uchar> &p, float f) { putfloat_(p, f); }
152 
getfloat(ucharbuf & p)153 float getfloat(ucharbuf &p)
154 {
155     float f;
156     p.get((uchar *)&f, sizeof(float));
157     return lilswap(f);
158 }
159 
160 template<class T>
sendstring_(const char * t,T & p)161 static inline void sendstring_(const char *t, T &p)
162 {
163     while(*t) putint(p, *t++);
164     putint(p, 0);
165 }
sendstring(const char * t,ucharbuf & p)166 void sendstring(const char *t, ucharbuf &p) { sendstring_(t, p); }
sendstring(const char * t,packetbuf & p)167 void sendstring(const char *t, packetbuf &p) { sendstring_(t, p); }
sendstring(const char * t,vector<uchar> & p)168 void sendstring(const char *t, vector<uchar> &p) { sendstring_(t, p); }
169 
getstring(char * text,ucharbuf & p,size_t len)170 void getstring(char *text, ucharbuf &p, size_t len)
171 {
172     char *t = text;
173     do
174     {
175         if(t>=&text[len]) { text[len-1] = 0; return; }
176         if(!p.remaining()) { *t = 0; return; }
177         *t = getint(p);
178     }
179     while(*t++);
180 }
181 
filtertext(char * dst,const char * src,bool whitespace,size_t len)182 void filtertext(char *dst, const char *src, bool whitespace, size_t len)
183 {
184     for(int c = uchar(*src); c; c = uchar(*++src))
185     {
186         if(c == '\f')
187         {
188             if(!*++src) break;
189             continue;
190         }
191         if(iscubeprint(c) || (iscubespace(c) && whitespace))
192         {
193             *dst++ = c;
194             if(!--len) break;
195         }
196     }
197     *dst = '\0';
198 }
199 
200