ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/include/common/util.h
Revision: 1.5
Committed: Wed Sep 5 11:23:13 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.4: +7 -17 lines
Log Message:
removed GPLed code and put license back to BSD

File Contents

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