ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/util.h
Revision: 1.35
Committed: Fri Jan 19 22:47:57 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.34: +5 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #ifndef UTIL_H__
2 #define UTIL_H__
3
4 #if __GNUC__ >= 3
5 # define is_constant(c) __builtin_constant_p (c)
6 #else
7 # define is_constant(c) 0
8 #endif
9
10 #include <cstddef>
11 #include <cmath>
12 #include <new>
13 #include <vector>
14
15 #include <glib.h>
16
17 #include <shstr.h>
18 #include <traits.h>
19
20 // use a gcc extension for auto declarations until ISO C++ sanctifies them
21 #define AUTODECL(var,expr) typeof(expr) var = (expr)
22
23 // very ugly macro that basicaly declares and initialises a variable
24 // that is in scope for the next statement only
25 // works only for stuff that can be assigned 0 and converts to false
26 // (note: works great for pointers)
27 // most ugly macro I ever wrote
28 #define declvar(type, name, value) if (type name = 0) { } else if (((name) = (value)), 1)
29
30 // in range including end
31 #define IN_RANGE_INC(val,beg,end) \
32 ((unsigned int)(val) - (unsigned int)(beg) <= (unsigned int)(end) - (unsigned int)(beg))
33
34 // in range excluding end
35 #define IN_RANGE_EXC(val,beg,end) \
36 ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg))
37
38 void fork_abort (const char *msg);
39
40 // rationale for using (U) not (T) is to reduce signed/unsigned issues,
41 // as a is often a constant while b is the variable. it is still a bug, though.
42 template<typename T, typename U> static inline T min (T a, U b) { return (U)a < b ? (U)a : b; }
43 template<typename T, typename U> static inline T max (T a, U b) { return (U)a > b ? (U)a : b; }
44 template<typename T, typename U, typename V> static inline T clamp (T v, U a, V b) { return v < (T)a ? (T)a : v >(T)b ? (T)b : v; }
45
46 template<typename T, typename U> static inline void swap (T& a, U& b) { T t=a; a=(T)b; b=(U)t; }
47
48 // this is much faster than crossfires original algorithm
49 // on modern cpus
50 inline int
51 isqrt (int n)
52 {
53 return (int)sqrtf ((float)n);
54 }
55
56 // this is only twice as fast as naive sqrtf (dx*dy+dy*dy)
57 #if 0
58 // and has a max. error of 6 in the range -100..+100.
59 #else
60 // and has a max. error of 9 in the range -100..+100.
61 #endif
62 inline int
63 idistance (int dx, int dy)
64 {
65 unsigned int dx_ = abs (dx);
66 unsigned int dy_ = abs (dy);
67
68 #if 0
69 return dx_ > dy_
70 ? (dx_ * 61685 + dy_ * 26870) >> 16
71 : (dy_ * 61685 + dx_ * 26870) >> 16;
72 #else
73 return dx_ + dy_ - min (dx_, dy_) * 5 / 8;
74 #endif
75 }
76
77 /*
78 * absdir(int): Returns a number between 1 and 8, which represent
79 * the "absolute" direction of a number (it actually takes care of
80 * "overflow" in previous calculations of a direction).
81 */
82 inline int
83 absdir (int d)
84 {
85 return ((d - 1) & 7) + 1;
86 }
87
88 // makes dynamically allocated objects zero-initialised
89 struct zero_initialised
90 {
91 void *operator new (size_t s, void *p)
92 {
93 memset (p, 0, s);
94 return p;
95 }
96
97 void *operator new (size_t s)
98 {
99 return g_slice_alloc0 (s);
100 }
101
102 void *operator new[] (size_t s)
103 {
104 return g_slice_alloc0 (s);
105 }
106
107 void operator delete (void *p, size_t s)
108 {
109 g_slice_free1 (s, p);
110 }
111
112 void operator delete[] (void *p, size_t s)
113 {
114 g_slice_free1 (s, p);
115 }
116 };
117
118 void *salloc_ (int n) throw (std::bad_alloc);
119 void *salloc_ (int n, void *src) throw (std::bad_alloc);
120
121 // strictly the same as g_slice_alloc, but never returns 0
122 template<typename T>
123 inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); }
124
125 // also copies src into the new area, like "memdup"
126 // if src is 0, clears the memory
127 template<typename T>
128 inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); }
129
130 // clears the memory
131 template<typename T>
132 inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); }
133
134 // for symmetry
135 template<typename T>
136 inline void sfree (T *ptr, int n = 1) throw ()
137 {
138 g_slice_free1 (n * sizeof (T), (void *)ptr);
139 }
140
141 // a STL-compatible allocator that uses g_slice
142 // boy, this is verbose
143 template<typename Tp>
144 struct slice_allocator
145 {
146 typedef size_t size_type;
147 typedef ptrdiff_t difference_type;
148 typedef Tp *pointer;
149 typedef const Tp *const_pointer;
150 typedef Tp &reference;
151 typedef const Tp &const_reference;
152 typedef Tp value_type;
153
154 template <class U>
155 struct rebind
156 {
157 typedef slice_allocator<U> other;
158 };
159
160 slice_allocator () throw () { }
161 slice_allocator (const slice_allocator &o) throw () { }
162 template<typename Tp2>
163 slice_allocator (const slice_allocator<Tp2> &) throw () { }
164
165 ~slice_allocator () { }
166
167 pointer address (reference x) const { return &x; }
168 const_pointer address (const_reference x) const { return &x; }
169
170 pointer allocate (size_type n, const_pointer = 0)
171 {
172 return salloc<Tp> (n);
173 }
174
175 void deallocate (pointer p, size_type n)
176 {
177 sfree<Tp> (p, n);
178 }
179
180 size_type max_size ()const throw ()
181 {
182 return size_t (-1) / sizeof (Tp);
183 }
184
185 void construct (pointer p, const Tp &val)
186 {
187 ::new (p) Tp (val);
188 }
189
190 void destroy (pointer p)
191 {
192 p->~Tp ();
193 }
194 };
195
196 // P. L'Ecuyer, “Maximally Equidistributed Combined Tausworthe Generators”, Mathematics of Computation, 65, 213 (1996), 203–213.
197 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
198 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
199 struct tausworthe_random_generator
200 {
201 // generator
202 uint32_t state [4];
203
204 void operator =(const tausworthe_random_generator &src)
205 {
206 state [0] = src.state [0];
207 state [1] = src.state [1];
208 state [2] = src.state [2];
209 state [3] = src.state [3];
210 }
211
212 void seed (uint32_t seed);
213 uint32_t next ();
214
215 // uniform distribution
216 uint32_t operator ()(uint32_t r_max)
217 {
218 return is_constant (r_max)
219 ? this->next () % r_max
220 : get_range (r_max);
221 }
222
223 // return a number within (min .. max)
224 int operator () (int r_min, int r_max)
225 {
226 return is_constant (r_min) && is_constant (r_max)
227 ? r_min + (*this) (max (r_max - r_min + 1, 1))
228 : get_range (r_min, r_max);
229 }
230
231 double operator ()()
232 {
233 return this->next () / (double)0xFFFFFFFFU;
234 }
235
236 protected:
237 uint32_t get_range (uint32_t r_max);
238 int get_range (int r_min, int r_max);
239 };
240
241 typedef tausworthe_random_generator rand_gen;
242
243 extern rand_gen rndm;
244
245 template<class T>
246 struct refptr
247 {
248 T *p;
249
250 refptr () : p(0) { }
251 refptr (const refptr<T> &p) : p(p.p) { if (p) p->refcnt_inc (); }
252 refptr (T *p) : p(p) { if (p) p->refcnt_inc (); }
253 ~refptr () { if (p) p->refcnt_dec (); }
254
255 const refptr<T> &operator =(T *o)
256 {
257 if (p) p->refcnt_dec ();
258 p = o;
259 if (p) p->refcnt_inc ();
260
261 return *this;
262 }
263
264 const refptr<T> &operator =(const refptr<T> o)
265 {
266 *this = o.p;
267 return *this;
268 }
269
270 T &operator * () const { return *p; }
271 T *operator ->() const { return p; }
272
273 operator T *() const { return p; }
274 };
275
276 typedef refptr<maptile> maptile_ptr;
277 typedef refptr<object> object_ptr;
278 typedef refptr<archetype> arch_ptr;
279 typedef refptr<client> client_ptr;
280 typedef refptr<player> player_ptr;
281
282 struct str_hash
283 {
284 std::size_t operator ()(const char *s) const
285 {
286 unsigned long hash = 0;
287
288 /* use the one-at-a-time hash function, which supposedly is
289 * better than the djb2-like one used by perl5.005, but
290 * certainly is better then the bug used here before.
291 * see http://burtleburtle.net/bob/hash/doobs.html
292 */
293 while (*s)
294 {
295 hash += *s++;
296 hash += hash << 10;
297 hash ^= hash >> 6;
298 }
299
300 hash += hash << 3;
301 hash ^= hash >> 11;
302 hash += hash << 15;
303
304 return hash;
305 }
306 };
307
308 struct str_equal
309 {
310 bool operator ()(const char *a, const char *b) const
311 {
312 return !strcmp (a, b);
313 }
314 };
315
316 template<class T>
317 struct unordered_vector : std::vector<T, slice_allocator<T> >
318 {
319 typedef typename unordered_vector::iterator iterator;
320
321 void erase (unsigned int pos)
322 {
323 if (pos < this->size () - 1)
324 (*this)[pos] = (*this)[this->size () - 1];
325
326 this->pop_back ();
327 }
328
329 void erase (iterator i)
330 {
331 erase ((unsigned int )(i - this->begin ()));
332 }
333 };
334
335 template<class T, int T::* index>
336 struct object_vector : std::vector<T *, slice_allocator<T *> >
337 {
338 void insert (T *obj)
339 {
340 assert (!(obj->*index));
341 push_back (obj);
342 obj->*index = this->size ();
343 }
344
345 void insert (T &obj)
346 {
347 insert (&obj);
348 }
349
350 void erase (T *obj)
351 {
352 assert (obj->*index);
353 int pos = obj->*index;
354 obj->*index = 0;
355
356 if (pos < this->size ())
357 {
358 (*this)[pos - 1] = (*this)[this->size () - 1];
359 (*this)[pos - 1]->*index = pos;
360 }
361
362 this->pop_back ();
363 }
364
365 void erase (T &obj)
366 {
367 errase (&obj);
368 }
369 };
370
371 // basically does what strncpy should do, but appends "..." to strings exceeding length
372 void assign (char *dst, const char *src, int maxlen);
373
374 // type-safe version of assign
375 template<int N>
376 inline void assign (char (&dst)[N], const char *src)
377 {
378 assign ((char *)&dst, src, N);
379 }
380
381 typedef double tstamp;
382
383 // return current time as timestampe
384 tstamp now ();
385
386 int similar_direction (int a, int b);
387
388 #endif
389