ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.96
Committed: Mon Apr 5 20:33:13 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_0
Changes since 1.95: +6 -1 lines
Log Message:
fix get_levelnumber and rename it to ordinal, also allow more format buffers

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */
22
23 /*
24 * General convenience functions for deliantra.
25 */
26
27 #include <cstdlib>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <signal.h>
33
34 #include <global.h>
35 #include <material.h>
36 #include <object.h>
37
38 #include <sys/time.h>
39 #include <sys/resource.h>
40
41 #include <glib.h>
42
43 refcnt_base::refcnt_t refcnt_dummy;
44 ssize_t slice_alloc;
45 rand_gen rndm, rmg_rndm;
46
47 #if !GCC_VERSION(3,4)
48 int least_significant_bit (uint32_t x)
49 {
50 x &= -x; // this isolates the lowest bit
51
52 int r = 0;
53
54 if (x & 0xaaaaaaaa) r += 1;
55 if (x & 0xcccccccc) r += 2;
56 if (x & 0xf0f0f0f0) r += 4;
57 if (x & 0xff00ff00) r += 8;
58 if (x & 0xffff0000) r += 16;
59
60 return r;
61 }
62 #endif
63
64 void
65 tausworthe_random_generator::seed (uint32_t seed)
66 {
67 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U;
68 state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U;
69 state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U;
70 state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U;
71
72 for (int i = 11; --i; )
73 next ();
74 }
75
76 uint32_t
77 tausworthe_random_generator::next ()
78 {
79 state [0] = ((state [0] & 0xFFFFFFFEU) << 18U) ^ (((state [0] << 6U) ^ state [0]) >> 13U);
80 state [1] = ((state [1] & 0xFFFFFFF8U) << 2U) ^ (((state [1] << 2U) ^ state [1]) >> 27U);
81 state [2] = ((state [2] & 0xFFFFFFF0U) << 7U) ^ (((state [2] << 13U) ^ state [2]) >> 21U);
82 state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U);
83
84 return state [0] ^ state [1] ^ state [2] ^ state [3];
85 }
86
87 template<class generator>
88 uint32_t
89 random_number_generator<generator>::get_range (uint32_t num)
90 {
91 return (this->next () * (uint64_t)num) >> 32U;
92 }
93
94 // return a number within (min .. max)
95 template<class generator>
96 int
97 random_number_generator<generator>::get_range (int r_min, int r_max)
98 {
99 return r_min + get_range (max (r_max - r_min + 1, 0));
100 }
101
102 template struct random_number_generator<tausworthe_random_generator>;
103 template struct random_number_generator<xorshift_random_generator>;
104
105 /******************************************************************************/
106
107 /* Checks a player-provided string which will become the msg property of
108 * an object for dangerous input.
109 */
110 bool
111 msg_is_safe (const char *msg)
112 {
113 bool safe = true;
114
115 /* Trying to cheat by getting data into the object */
116 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
117 || strstr (msg, "\nendmsg"))
118 safe = false;
119
120 /* Trying to make the object talk, and potentially access arbitrary code */
121 if (object::msg_has_dialogue (msg))
122 safe = false;
123
124 return safe;
125 }
126
127 /////////////////////////////////////////////////////////////////////////////
128
129 void
130 fork_abort (const char *msg)
131 {
132 if (!fork ())
133 {
134 signal (SIGINT , SIG_IGN);
135 signal (SIGTERM, SIG_IGN);
136 signal (SIGABRT, SIG_IGN);
137
138 signal (SIGSEGV, SIG_DFL);
139 signal (SIGBUS , SIG_DFL);
140 signal (SIGILL , SIG_DFL);
141 signal (SIGTRAP, SIG_DFL);
142
143 // try to put corefiles into a subdirectory, if existing, to allow
144 // an administrator to reduce the I/O load.
145 chdir ("cores");
146
147 // try to detach us from as many external dependencies as possible
148 // as coredumping can take time by closing all fd's.
149 {
150 struct rlimit lim;
151
152 if (getrlimit (RLIMIT_NOFILE, &lim))
153 lim.rlim_cur = 1024;
154
155 for (int i = 0; i < lim.rlim_cur; ++i)
156 close (i);
157 }
158
159 {
160 sigset_t empty;
161 sigemptyset (&empty);
162 sigprocmask (SIG_SETMASK, &empty, 0);
163 }
164
165 // try to coredump with SIGTRAP
166 kill (getpid (), SIGTRAP);
167 abort ();
168 }
169
170 LOG (llevError, "fork abort: %s\n", msg);
171 }
172
173 void *salloc_ (int n) throw (std::bad_alloc)
174 {
175 void *ptr = g_slice_alloc (n);
176
177 if (!ptr)
178 throw std::bad_alloc ();
179
180 slice_alloc += n;
181 return ptr;
182 }
183
184 void *salloc_ (int n, void *src) throw (std::bad_alloc)
185 {
186 void *ptr = salloc_ (n);
187
188 if (src)
189 memcpy (ptr, src, n);
190 else
191 memset (ptr, 0, n);
192
193 return ptr;
194 }
195
196 /******************************************************************************/
197
198 #if DEBUG_SALLOC
199
200 #define MAGIC 0xa1b2c35543deadLL
201
202 void *g_slice_alloc (unsigned long size)
203 {
204 unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
205 *p++ = size ^ MAGIC;
206 //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
207 return (void *)p;
208 }
209
210 void *g_slice_alloc0 (unsigned long size)
211 {
212 return memset (g_slice_alloc (size), 0, size);
213 }
214
215 void g_slice_free1 (unsigned long size, void *ptr)
216 {
217 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
218 if (expect_true (ptr))
219 {
220 unsigned long *p = (unsigned long *)ptr;
221 unsigned long s = *--p ^ MAGIC;
222
223 if (size != (unsigned long)(*p ^ MAGIC))
224 {
225 LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
226 abort ();
227 }
228
229 *p = MAGIC;
230
231 (g_slice_free1)(s + sizeof (unsigned long), p);
232 }
233 }
234
235 #endif
236
237 /******************************************************************************/
238
239 int
240 assign (char *dst, const char *src, int maxsize)
241 {
242 if (!src)
243 src = "";
244
245 int len = strlen (src);
246
247 if (len >= maxsize)
248 {
249 if (maxsize <= 4)
250 {
251 memset (dst, '.', maxsize - 2);
252 dst [maxsize - 1] = 0;
253 }
254 else
255 {
256 memcpy (dst, src, maxsize - 4);
257 memcpy (dst + maxsize - 4, "...", 4);
258 }
259
260 len = maxsize;
261 }
262 else
263 memcpy (dst, src, ++len);
264
265 return len;
266 }
267
268 char *
269 vformat (const char *format, va_list ap)
270 {
271 static dynbuf_text bufs[8];
272 static int bufidx;
273
274 dynbuf_text &buf = bufs [++bufidx & 7];
275
276 buf.clear ();
277 buf.vprintf (format, ap);
278 return buf;
279 }
280
281 char *
282 format (const char *format, ...)
283 {
284 va_list ap;
285 va_start (ap, format);
286 char *buf = vformat (format, ap);
287 va_end (ap);
288
289 return buf;
290 }
291
292 tstamp now ()
293 {
294 struct timeval tv;
295
296 gettimeofday (&tv, 0);
297 return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
298 }
299
300 int
301 similar_direction (int a, int b)
302 {
303 if (!a || !b)
304 return 0;
305
306 int diff = (b - a) & 7;
307 return diff <= 1 || diff >= 7;
308 }
309
310 /* crc32 0xdebb20e3 table and supplementary functions. */
311 extern const uint32_t crc_32_tab[256] =
312 {
313 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
314 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
315 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
316 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
317 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
318 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
319 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
320 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
321 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
322 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
323 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
324 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
325 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
326 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
327 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
328 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
329 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
330 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
331 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
332 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
333 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
334 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
335 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
336 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
337 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
338 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
339 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
340 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
341 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
342 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
343 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
344 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
345 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
346 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
347 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
348 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
349 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
350 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
351 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
352 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
353 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
354 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
355 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
356 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
357 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
358 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
359 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
360 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
361 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
362 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
363 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
364 0x2d02ef8dL
365 };
366
367 void thread::start (void *(*start_routine)(void *), void *arg)
368 {
369 pthread_attr_t attr;
370
371 pthread_attr_init (&attr);
372 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
373 pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
374 ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
375 #ifdef PTHREAD_SCOPE_PROCESS
376 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
377 #endif
378
379 sigset_t fullsigset, oldsigset;
380 sigfillset (&fullsigset);
381
382 pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
383
384 if (pthread_create (&id, &attr, start_routine, arg))
385 cleanup ("unable to create a new thread");
386
387 pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
388 }
389