ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/include/common/util.h
Revision: 1.8
Committed: Sat Sep 22 14:27:26 2007 UTC (19 years ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +1 -1 lines
State: FILE REMOVED
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# User Rev Content
1 pippijn 1.7 /**
2     * util.h: Various utility functions.
3     *
4 pippijn 1.2 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 pippijn 1.7 * Rights to this code are as documented in doc/pod/gplicense.pod.
6 pippijn 1.2 *
7 pippijn 1.8 * $Id: util.h,v 1.7 2007-09-16 18:54:42 pippijn Exp $
8 pippijn 1.2 */
9    
10 pippijn 1.1 #ifndef UTIL_H
11     #define UTIL_H
12    
13 pippijn 1.6 #include <sysconf.h>
14    
15 pippijn 1.1 #include <climits>
16     #include <cstddef>
17     #include <vector>
18    
19 pippijn 1.3 #include <ermyth/exception.h>
20 pippijn 1.1
21 pippijn 1.6 #include <sys/time.h>
22    
23 pippijn 1.1 /**
24     * Mostly the same as std::vector, but erase can reorder
25     * the elements, making insert/remove O(1) instead of O(n).
26     *
27     * NOTE: only some forms of erase are available
28     * (Taken from Crossfire TRT http://cf.schmorp.de/)
29     */
30     template<typename T, typename Alloc = std::allocator<T> >
31     struct unordered_vector : std::vector<T, Alloc>
32     {
33     typedef typename unordered_vector::iterator iterator;
34    
35     void erase (unsigned pos)
36     {
37     if (pos < this->size () - 1)
38     (*this)[pos] = (*this)[this->size () - 1];
39    
40     this->pop_back ();
41     }
42    
43     void erase (iterator pos)
44     {
45     erase ((unsigned)(pos - this->begin ()));
46     }
47    
48     void insert (T const &val)
49     {
50     push_back (val);
51     }
52     };
53    
54     /**
55     * The following templates find a sufficiently large integer type to contain
56     * the given number of bits.
57     *
58     * Usage:
59     *
60     * unsigned_type<16>::type a; // 16-bit unsigned if available (probably unsigned short)
61     * signed_type<8>::type a; // 8-bit signed if available (probably char)
62     */
63    
64     // Empty class if everything failed
65     struct empty_base
66     {
67     };
68    
69     // To allow inheritance from this and get the integer type out
70     template<typename T>
71     struct identity
72     {
73     typedef T type;
74     };
75    
76     /**
77     * The following two templates are a compile-time if-statement.
78     */
79     template<bool Cond, class Then, class Else>
80     struct If
81     {
82     typedef Then ret;
83     };
84    
85     template<class Then, class Else>
86     struct If<false, Then, Else>
87     {
88     typedef Else ret;
89     };
90    
91     // Looks whether the desired type exists
92     template<typename T, std::size_t bits, typename Else>
93     struct type_if_size
94     : If<sizeof (T) * CHAR_BIT >= bits, identity<T>, Else>::ret
95     {
96     };
97    
98     template<std::size_t bits>
99     struct unsigned_type
100     : type_if_size<unsigned char, bits,
101     type_if_size<unsigned short, bits,
102     type_if_size<unsigned int, bits,
103     type_if_size<unsigned long, bits,
104     empty_base // No such type
105     >
106     >
107     >
108     >
109     {
110     };
111    
112     template<std::size_t bits>
113     struct signed_type
114     : type_if_size<signed char, bits
115     , type_if_size<signed short, bits
116     , type_if_size<signed int, bits
117     , type_if_size<signed long, bits
118     , empty_base // No such type
119     >
120     >
121     >
122     >
123     {
124     };
125    
126 pippijn 1.3 // This is a vector that stores each element's index in the object.
127     // This only works for pointers to objects.
128 pippijn 1.6 template<class T, unsigned T::*index = &T::index, class Alloc = std::allocator<T *> >
129 pippijn 1.1 struct indexing_vector : std::vector<T *, Alloc>
130     {
131     typedef typename indexing_vector::size_type size_type;
132     typedef typename indexing_vector::iterator iterator;
133    
134 pippijn 1.3 iterator find (const T *obj)
135     {
136     return obj->*index
137     ? this->begin () + obj->*index - 1
138     : this->end ();
139     }
140    
141 pippijn 1.1 void erase (T *obj)
142     {
143 pippijn 1.6 unsigned pos = obj->*index;
144 pippijn 1.1 obj->*index = 0;
145    
146 pippijn 1.3 if (pos < this->size ())
147 pippijn 1.1 {
148 pippijn 1.3 (*this)[pos - 1] = (*this)[this->size () - 1];
149     (*this)[pos - 1]->*index = pos;
150 pippijn 1.1 }
151    
152     this->pop_back ();
153     }
154    
155     void insert (T *obj)
156     {
157     this->push_back (obj);
158     obj->*index = this->size ();
159     }
160     };
161    
162     struct str_hash
163     {
164     std::size_t operator () (char const *s) const
165     {
166     unsigned long hash = 0;
167    
168     // use the one-at-a-time hash function.
169     // see http://burtleburtle.net/bob/hash/doobs.html
170     while (*s)
171     {
172     hash += *s++;
173     hash += hash << 10;
174     hash ^= hash >> 6;
175     }
176    
177     hash += hash << 3;
178     hash ^= hash >> 11;
179     hash += hash << 15;
180    
181     return hash;
182     }
183     };
184    
185     struct str_eq
186     {
187     bool operator () (char const * const s1, char const * const s2) const
188     {
189     if (s1 == NULL || s2 == NULL)
190     throw nullpointer_exception ();
191     return !strcmp (s1, s2);
192     }
193     };
194    
195     struct str_lt
196     {
197     bool operator () (char const * const s1, char const * const s2) const
198     {
199     if (s1 == NULL || s2 == NULL)
200     throw nullpointer_exception ();
201     return strcmp (s1, s2) < 0;
202     }
203     };
204    
205 pippijn 1.3 E int irccasecmp (char const * const s1, char const * const s2);
206     E int ircncasecmp (char const * const s1, char const * const s2, int maxlen);
207    
208     struct irccase_lt
209     {
210     bool operator () (char const * const s1, char const * const s2) const
211     {
212     if (s1 == NULL || s2 == NULL)
213     throw nullpointer_exception ();
214     return irccasecmp (s1, s2) < 0;
215     }
216     };
217    
218 pippijn 1.5 typedef double tstamp;
219    
220     inline tstamp
221 pippijn 1.3 now ()
222     {
223     #ifdef HAVE_GETTIMEOFDAY
224     struct timeval tv;
225    
226     gettimeofday (&tv, 0);
227 pippijn 1.5 return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
228 pippijn 1.3 #else
229 pippijn 1.5 return tstamp (time (NULL));
230 pippijn 1.3 #endif
231     }
232    
233 pippijn 1.4 #if 0
234     /**
235     * Comma delimited output to std::cout
236     */
237    
238     namespace impl
239     {
240     struct C
241     {
242     template<typename T>
243     C operator << (T const &t) const
244     {
245     std::cout << ", " << t;
246     return C();
247     }
248    
249     C operator << (std::ostream &(* const f) (std::ostream &)) const
250     {
251     std::cout << f;
252     return C();
253     }
254    
255     C operator << (std::ios_base &(* const f) (std::ios_base &)) const
256     {
257     std::cout << f;
258     return C();
259     }
260     };
261    
262     enum Del
263     {
264     del
265     };
266    
267     template<typename T>
268     C operator << (Del, T const &t)
269     {
270     std::cout << t;
271     return C();
272     }
273    
274     inline Del
275     operator << (Del, std::ostream &(* const f) (std::ostream &))
276     {
277     std::cout << f;
278     return del;
279     }
280    
281     inline Del
282     operator << (Del, std::ios_base &(* const f) (std::ios_base &))
283     {
284     std::cout << f;
285     return del;
286     }
287    
288     // The <<'s taking std::ios_base&(std::ios_base&)'s are for things like std::hex.
289     // The <<'s taking std::ostream&(std::ostream&)'s are for things like std::endl.
290    
291     inline Del
292     operator << (std::ostream &, Del)
293     {
294     return del;
295     }
296     // To allow: std::cout << del << 2 << 4
297     }
298    
299     using impl::del;
300     #endif
301    
302     // Allow pasting things, even if one of the arguments is a macro itself
303     #define PASTE(A, B) DOPASTE (A, B)
304     #define DOPASTE(A, B) DODOPASTE (A, B)
305     #define DODOPASTE(A, B) A ## B
306    
307     #define PASTE3(A, B, C) PASTE (PASTE (A, B), C)
308     #define PASTE4(A, B, C, D) PASTE (PASTE3 (A, B, C), D)
309     #define PASTE5(A, B, C, D, E) PASTE (PASTE4 (A, B, C, D), E)
310     #define PASTE6(A, B, C, D, E, F) PASTE (PASTE5 (A, B, C, D, E), F)
311    
312     namespace impl
313     {
314     template<bool>
315     struct static_assert;
316    
317     template<>
318     struct static_assert<true>
319     {
320     };
321     }
322    
323     #define static_assert(cond) ::impl::static_assert<(cond)> PASTE (static_assert_, __LINE__)
324 pippijn 1.3
325 pippijn 1.6 E int itoa (uint32_t n, char *buf, int buflen);
326     E int itoa (uint64_t n, char *buf, int buflen);
327    
328     inline int
329     itoa (int32_t n, char *buf, int buflen)
330     {
331     *buf = '-';
332     buf += (n < 0);
333     uint32_t u = n < 0 ? -n : n;
334     return itoa (u, buf, buflen - 1);
335     }
336    
337     inline int
338     itoa (int64_t n, char *buf, int buflen)
339     {
340     *buf = '-';
341     buf += (n < 0);
342     uint64_t u = n < 0 ? -n : n;
343     return itoa (u, buf, buflen - 1);
344     }
345    
346     template<typename IntType, int N>
347     inline int
348     itoa (IntType n, char (&buf)[N])
349     {
350     return itoa (n, buf, N);
351     }
352    
353 pippijn 1.1 #endif