ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/include/common/util.h
Revision: 1.4
Committed: Thu Aug 30 19:56:20 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +92 -1 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

File Contents

# User Rev Content
1 pippijn 1.2 /*
2     * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
3     * Rights to this code are as documented in doc/pod/gplicense.pod.
4     *
5     * Various utility functions.
6     *
7 pippijn 1.4 * $Id: util.h,v 1.3 2007-08-28 17:08:07 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     //
125     // Based on the object_vector from Crossfire TRT
126 pippijn 1.1 template<class T, int T::*index = &T::index, class Alloc = std::allocator<T *> >
127     struct indexing_vector : std::vector<T *, Alloc>
128     {
129     typedef typename indexing_vector::size_type size_type;
130     typedef typename indexing_vector::iterator iterator;
131    
132 pippijn 1.3 iterator find (const T *obj)
133     {
134     return obj->*index
135     ? this->begin () + obj->*index - 1
136     : this->end ();
137     }
138    
139     iterator find (const T &obj)
140     {
141     return find (&obj);
142     }
143    
144 pippijn 1.1 void erase (T *obj)
145     {
146 pippijn 1.3 unsigned int pos = obj->*index;
147 pippijn 1.1 obj->*index = 0;
148    
149 pippijn 1.3 if (pos < this->size ())
150 pippijn 1.1 {
151 pippijn 1.3 (*this)[pos - 1] = (*this)[this->size () - 1];
152     (*this)[pos - 1]->*index = pos;
153 pippijn 1.1 }
154    
155     this->pop_back ();
156     }
157    
158 pippijn 1.3 void erase (T &obj)
159     {
160     erase (&obj);
161     }
162    
163 pippijn 1.1 void insert (T *obj)
164     {
165     this->push_back (obj);
166     obj->*index = this->size ();
167     }
168     };
169    
170     struct str_hash
171     {
172     std::size_t operator () (char const *s) const
173     {
174     unsigned long hash = 0;
175    
176     // use the one-at-a-time hash function.
177     // see http://burtleburtle.net/bob/hash/doobs.html
178     while (*s)
179     {
180     hash += *s++;
181     hash += hash << 10;
182     hash ^= hash >> 6;
183     }
184    
185     hash += hash << 3;
186     hash ^= hash >> 11;
187     hash += hash << 15;
188    
189     return hash;
190     }
191     };
192    
193     struct str_eq
194     {
195     bool operator () (char const * const s1, char const * const s2) const
196     {
197     if (s1 == NULL || s2 == NULL)
198     throw nullpointer_exception ();
199     return !strcmp (s1, s2);
200     }
201     };
202    
203     struct str_lt
204     {
205     bool operator () (char const * const s1, char const * const s2) const
206     {
207     if (s1 == NULL || s2 == NULL)
208     throw nullpointer_exception ();
209     return strcmp (s1, s2) < 0;
210     }
211     };
212    
213 pippijn 1.3 E int irccasecmp (char const * const s1, char const * const s2);
214     E int ircncasecmp (char const * const s1, char const * const s2, int maxlen);
215    
216     struct irccase_lt
217     {
218     bool operator () (char const * const s1, char const * const s2) const
219     {
220     if (s1 == NULL || s2 == NULL)
221     throw nullpointer_exception ();
222     return irccasecmp (s1, s2) < 0;
223     }
224     };
225    
226     inline double
227     now ()
228     {
229     #ifdef HAVE_GETTIMEOFDAY
230     struct timeval tv;
231    
232     gettimeofday (&tv, 0);
233     return double (tv.tv_sec) + double (tv.tv_usec) * double (1e-6);
234     #else
235     return double (time (NULL));
236     #endif
237     }
238    
239 pippijn 1.4 #if 0
240     /**
241     * Comma delimited output to std::cout
242     */
243    
244     namespace impl
245     {
246     struct C
247     {
248     template<typename T>
249     C operator << (T const &t) const
250     {
251     std::cout << ", " << t;
252     return C();
253     }
254    
255     C operator << (std::ostream &(* const f) (std::ostream &)) const
256     {
257     std::cout << f;
258     return C();
259     }
260    
261     C operator << (std::ios_base &(* const f) (std::ios_base &)) const
262     {
263     std::cout << f;
264     return C();
265     }
266     };
267    
268     enum Del
269     {
270     del
271     };
272    
273     template<typename T>
274     C operator << (Del, T const &t)
275     {
276     std::cout << t;
277     return C();
278     }
279    
280     inline Del
281     operator << (Del, std::ostream &(* const f) (std::ostream &))
282     {
283     std::cout << f;
284     return del;
285     }
286    
287     inline Del
288     operator << (Del, std::ios_base &(* const f) (std::ios_base &))
289     {
290     std::cout << f;
291     return del;
292     }
293    
294     // The <<'s taking std::ios_base&(std::ios_base&)'s are for things like std::hex.
295     // The <<'s taking std::ostream&(std::ostream&)'s are for things like std::endl.
296    
297     inline Del
298     operator << (std::ostream &, Del)
299     {
300     return del;
301     }
302     // To allow: std::cout << del << 2 << 4
303     }
304    
305     using impl::del;
306     #endif
307    
308     // Allow pasting things, even if one of the arguments is a macro itself
309     #define PASTE(A, B) DOPASTE (A, B)
310     #define DOPASTE(A, B) DODOPASTE (A, B)
311     #define DODOPASTE(A, B) A ## B
312    
313     #define PASTE3(A, B, C) PASTE (PASTE (A, B), C)
314     #define PASTE4(A, B, C, D) PASTE (PASTE3 (A, B, C), D)
315     #define PASTE5(A, B, C, D, E) PASTE (PASTE4 (A, B, C, D), E)
316     #define PASTE6(A, B, C, D, E, F) PASTE (PASTE5 (A, B, C, D, E), F)
317    
318     namespace impl
319     {
320     template<bool>
321     struct static_assert;
322    
323     template<>
324     struct static_assert<true>
325     {
326     };
327     }
328    
329     #define static_assert(cond) ::impl::static_assert<(cond)> PASTE (static_assert_, __LINE__)
330 pippijn 1.3
331 pippijn 1.1 #endif