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

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.39 *
4 root 1.95 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 pippijn 1.39 *
6 root 1.89 * 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 pippijn 1.39 *
11 root 1.60 * 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 pippijn 1.39 *
16 root 1.89 * 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 root 1.57 *
20 root 1.68 * The authors can be reached via e-mail to <support@deliantra.net>
21 pippijn 1.39 */
22 elmex 1.1
23     /*
24 root 1.92 * General convenience functions for deliantra.
25 elmex 1.1 */
26    
27 root 1.37 #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 elmex 1.1 #include <global.h>
35     #include <material.h>
36 sf-marcmagus 1.87 #include <object.h>
37 elmex 1.1
38 root 1.79 #include <sys/time.h>
39     #include <sys/resource.h>
40    
41 root 1.4 #include <glib.h>
42    
43 root 1.63 refcnt_base::refcnt_t refcnt_dummy;
44 root 1.74 ssize_t slice_alloc;
45 root 1.77 rand_gen rndm, rmg_rndm;
46 root 1.40
47 root 1.94 #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 root 1.42 void
65     tausworthe_random_generator::seed (uint32_t seed)
66 root 1.40 {
67 root 1.74 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 root 1.40
72     for (int i = 11; --i; )
73 root 1.84 next ();
74 root 1.40 }
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 root 1.84 template<class generator>
88 root 1.42 uint32_t
89 root 1.84 random_number_generator<generator>::get_range (uint32_t num)
90 root 1.42 {
91 root 1.84 return (this->next () * (uint64_t)num) >> 32U;
92 root 1.42 }
93    
94     // return a number within (min .. max)
95 root 1.84 template<class generator>
96 root 1.42 int
97 root 1.84 random_number_generator<generator>::get_range (int r_min, int r_max)
98 root 1.42 {
99 root 1.50 return r_min + get_range (max (r_max - r_min + 1, 0));
100 root 1.42 }
101    
102 root 1.84 template struct random_number_generator<tausworthe_random_generator>;
103     template struct random_number_generator<xorshift_random_generator>;
104    
105 sf-marcmagus 1.87 /******************************************************************************/
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 root 1.88 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
117     || strstr (msg, "\nendmsg"))
118 sf-marcmagus 1.87 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 root 1.14 /////////////////////////////////////////////////////////////////////////////
128    
129 root 1.37 void
130     fork_abort (const char *msg)
131     {
132     if (!fork ())
133     {
134 root 1.80 signal (SIGINT , SIG_IGN);
135     signal (SIGTERM, SIG_IGN);
136     signal (SIGABRT, SIG_IGN);
137 root 1.79
138 root 1.81 signal (SIGSEGV, SIG_DFL);
139     signal (SIGBUS , SIG_DFL);
140     signal (SIGILL , SIG_DFL);
141     signal (SIGTRAP, SIG_DFL);
142    
143 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
144     // an administrator to reduce the I/O load.
145     chdir ("cores");
146 root 1.79
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 root 1.81 {
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 root 1.37 abort ();
168     }
169    
170 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
171 root 1.37 }
172 root 1.38
173 root 1.25 void *salloc_ (int n) throw (std::bad_alloc)
174 root 1.10 {
175 root 1.25 void *ptr = g_slice_alloc (n);
176 root 1.13
177 root 1.23 if (!ptr)
178 root 1.13 throw std::bad_alloc ();
179 root 1.4
180 root 1.74 slice_alloc += n;
181 root 1.23 return ptr;
182     }
183    
184 root 1.25 void *salloc_ (int n, void *src) throw (std::bad_alloc)
185 root 1.23 {
186 root 1.25 void *ptr = salloc_ (n);
187 root 1.23
188 root 1.24 if (src)
189 root 1.25 memcpy (ptr, src, n);
190 root 1.24 else
191 root 1.25 memset (ptr, 0, n);
192 root 1.23
193     return ptr;
194 root 1.3 }
195 root 1.11
196 root 1.69 /******************************************************************************/
197    
198 root 1.72 #if DEBUG_SALLOC
199 root 1.69
200 root 1.70 #define MAGIC 0xa1b2c35543deadLL
201 root 1.69
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 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
218 root 1.69 if (expect_true (ptr))
219     {
220     unsigned long *p = (unsigned long *)ptr;
221     unsigned long s = *--p ^ MAGIC;
222    
223 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
224 root 1.74 {
225     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
226     abort ();
227     }
228 root 1.69
229     *p = MAGIC;
230    
231     (g_slice_free1)(s + sizeof (unsigned long), p);
232     }
233     }
234    
235     #endif
236    
237     /******************************************************************************/
238    
239 root 1.86 int
240     assign (char *dst, const char *src, int maxsize)
241 root 1.11 {
242     if (!src)
243     src = "";
244    
245     int len = strlen (src);
246    
247 root 1.86 if (len >= maxsize)
248 root 1.11 {
249 root 1.86 if (maxsize <= 4)
250 root 1.11 {
251 root 1.86 memset (dst, '.', maxsize - 2);
252     dst [maxsize - 1] = 0;
253 root 1.11 }
254     else
255     {
256 root 1.86 memcpy (dst, src, maxsize - 4);
257     memcpy (dst + maxsize - 4, "...", 4);
258 root 1.11 }
259 root 1.86
260     len = maxsize;
261 root 1.11 }
262     else
263 root 1.86 memcpy (dst, src, ++len);
264    
265     return len;
266 root 1.11 }
267    
268 root 1.90 char *
269     vformat (const char *format, va_list ap)
270     {
271 root 1.96 static dynbuf_text bufs[8];
272     static int bufidx;
273    
274     dynbuf_text &buf = bufs [++bufidx & 7];
275    
276     buf.clear ();
277 root 1.90 buf.vprintf (format, ap);
278     return buf;
279     }
280    
281     char *
282 root 1.51 format (const char *format, ...)
283     {
284 root 1.65 va_list ap;
285     va_start (ap, format);
286 root 1.90 char *buf = vformat (format, ap);
287 root 1.65 va_end (ap);
288    
289     return buf;
290 root 1.51 }
291    
292 root 1.23 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 root 1.17
300 root 1.32 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 root 1.48 /* 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 root 1.73 void thread::start (void *(*start_routine)(void *), void *arg)
368     {
369 root 1.75 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 root 1.73 sigset_t fullsigset, oldsigset;
380     sigfillset (&fullsigset);
381    
382     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
383    
384 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
385 root 1.73 cleanup ("unable to create a new thread");
386    
387     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
388     }
389 root 1.75