Abandon the socket properly when freeing a DC hub.
[doldaconnect.git] / include / utils.h
1 /*
2  *  Dolda Connect - Modular multiuser Direct Connect-style client
3  *  Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 #ifndef _UTILS_H
20 #define _UTILS_H
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #ifdef DAEMON
25 #include "log.h"
26 #endif
27
28 struct wcspair {
29     struct wcspair *next;
30     wchar_t *key;
31     wchar_t *val;
32 };
33
34 struct strpair {
35     struct strpair *next;
36     char *key;
37     char *val;
38 };
39
40 struct btree {
41     struct btree *l, *r;
42     int h;
43     void *d;
44 };
45
46 /* "Safe" functions */
47 #ifdef DAEMON
48 #define LOGOOM(size) flog(LOG_CRIT, "%s (%s:%i): out of memory (alloc %zi)", __FUNCTION__, __FILE__, __LINE__, (size))
49 #define smalloc(size) ({void *__result__; ((__result__ = malloc(size)) == NULL)?({LOGOOM((ssize_t)(size)); abort(); (void *)0;}):__result__;})
50 #define srealloc(ptr, size) ({void *__result__; ((__result__ = realloc((ptr), (size))) == NULL)?({LOGOOM((ssize_t)(size)); abort(); (void *)0;}):__result__;})
51 #define swcsdup(wcs) ({wchar_t *__eval__; __eval__ = (wcs); (wchar_t *)wcscpy(smalloc(sizeof(wchar_t) * (wcslen(__eval__) + 1)), __eval__);})
52 #define sstrdup(str) ((char *)strcpy(smalloc(strlen(str) + 1), (str)))
53 #else
54 #define LOGOOM(size)
55 #define smalloc(size) ({void *__result__; ((__result__ = malloc(size)) == NULL)?({exit(-1); (void *)0;}):__result__;})
56 #define srealloc(ptr, size) ({void *__result__; ((__result__ = realloc((ptr), (size))) == NULL)?({exit(-1); (void *)0;}):__result__;})
57 #define swcsdup(wcs) ((wchar_t *)wcscpy(smalloc(sizeof(wchar_t) * (wcslen(wcs) + 1)), (wcs)))
58 #define sstrdup(str) ((char *)strcpy(smalloc(strlen(str) + 1), (str)))
59 #endif
60
61 #define CBCHAIN(name, args...) \
62 struct cbchain_ ## name { \
63     struct cbchain_ ## name *next, *prev; \
64     int (*func)(args, void *data); \
65     void (*destroy)(void *data); \
66     void *data; \
67 } * name
68
69 #define GCBCHAIN(name, args...) \
70 struct cbchain_ ## name * name = NULL
71
72 #define EGCBCHAIN(name, args...) \
73 extern struct cbchain_ ## name { \
74     struct cbchain_ ## name *next, *prev; \
75     int (*func)(args, void *data); \
76     void *data; \
77 } * name
78
79 char *vsprintf2(char *format, va_list al);
80 char *sprintf2(char *format, ...)
81 #if defined(__GNUC__)
82     __attribute__ ((format (printf, 1, 2)))
83 #endif
84 ;
85 wchar_t *vswprintf2(wchar_t *format, va_list al);
86 wchar_t *swprintf2(wchar_t *format, ...);
87 int havecharset(char *charset);
88 wchar_t *icmbstowcs(char *mbs, char *charset);
89 wchar_t *icsmbstowcs(char *mbs, char *charset, wchar_t *def);
90 char *icwcstombs(wchar_t *wcs, char *charset);
91 char *icswcstombs(wchar_t *wcs, char *charset, char *def);
92 wchar_t *wcstolower(wchar_t *wcs);
93 wchar_t ucptowc(int ucp);
94 void _sizebuf(void **buf, size_t *bufsize, size_t reqsize, size_t elsize, int algo);
95 double ntime(void);
96 wchar_t *wcslower(wchar_t *wcs);
97 #ifndef HAVE_WCSCASECMP
98 int wcscasecmp(const wchar_t *s1, const wchar_t *s2);
99 #endif
100 char *hexencode(char *data, size_t datalen);
101 char *hexdecode(char *data, size_t *len);
102 char *base64encode(char *data, size_t datalen);
103 char *base64decode(char *data, size_t *datalen);
104 char *base32encode(char *data, size_t datalen);
105 char *base32decode(char *data, size_t *datalen);
106 void _freeparr(void **arr);
107 int _parrlen(void **arr);
108 char *findfile(char *name, char *homedir, int filldef);
109 struct strpair *newstrpair(char *key, char *val, struct strpair **list);
110 void freestrpair(struct strpair *pair, struct strpair **list);
111 char *spfind(struct strpair *list, char *key);
112 struct wcspair *newwcspair(wchar_t *key, wchar_t *val, struct wcspair **list);
113 void freewcspair(struct wcspair *pair, struct wcspair **list);
114 wchar_t *wpfind(struct wcspair *list, wchar_t *key);
115 int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *));
116 int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *));
117 void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *));
118 void *btreeiter(struct btree *tree);
119 void btreefree(struct btree *tree);
120
121 #define sizebuf(b, bs, rs, es, a) _sizebuf((void **)(void *)(b), (bs), (rs), (es), (a))
122 #define sizebuf2(b, rs, a) _sizebuf((void **)(void *)(&(b)), &(b ## size), (rs), sizeof(*(b)), (a))
123 #define addtobuf(b, c) \
124 do { \
125     _sizebuf((void **)(void *)(&(b)), &(b ## size), (b ## data) + 1, sizeof(*(b)), 1); \
126     (b)[(b ## data)++] = (c); \
127 } while(0)
128 #define bufcat(d, s, n) \
129 do { \
130     size_t __bufcat_size__; \
131     __bufcat_size__ = (n); \
132     _sizebuf((void **)(void *)(&(d)), &(d ## size), (d ## data) + __bufcat_size__, sizeof(*(d)), 1); \
133     memcpy((d) + (d ## data), (s), sizeof(*(d)) * __bufcat_size__); \
134     (d ## data) += __bufcat_size__; \
135 } while (0)
136 #define bprintf(b, fmt...) \
137     do { \
138         char *__bprintf_dest__; \
139         __bprintf_dest__ = sprintf2(fmt); \
140         bufcat(b, __bprintf_dest__, strlen(__bprintf_dest__)); \
141         free(__bprintf_dest__); \
142     } while(0)
143
144 #define freeparr(parr) _freeparr((void **)(parr))
145 #define parrlen(parr) _parrlen((void **)(parr))
146
147 #define CBREG(obj, name, funca, destroya, dataa) \
148 do { \
149     struct cbchain_ ## name *__new_cb__; \
150     __new_cb__ = smalloc(sizeof(*__new_cb__)); \
151     __new_cb__->func = funca; \
152     __new_cb__->destroy = destroya; \
153     __new_cb__->data = dataa; \
154     __new_cb__->prev = NULL; \
155     __new_cb__->next = (obj)->name; \
156     if((obj)->name != NULL) { \
157         (obj)->name->prev = __new_cb__; \
158     } \
159     (obj)->name = __new_cb__; \
160 } while(0)
161
162 #define CBUNREG(obj, name, dataa) \
163 do { \
164     struct cbchain_ ## name *__cur__; \
165     for(__cur__ = (obj)->name; __cur__ != NULL; __cur__ = __cur__->next) { \
166         if(__cur__->data == (dataa)) { \
167             if(__cur__->destroy != NULL) \
168                 __cur__->destroy(__cur__->data); \
169             if(__cur__->prev != NULL) \
170                 __cur__->prev->next = __cur__->next; \
171             if(__cur__->next != NULL) \
172                 __cur__->next->prev = __cur__->prev; \
173             if(__cur__ == (obj)->name) \
174                 (obj)->name = __cur__->next; \
175             free(__cur__); \
176             break; \
177         } \
178     } \
179 } while(0)
180
181 #define GCBREG(name, funca, dataa) \
182 do { \
183     struct cbchain_ ## name *__new_cb__; \
184     __new_cb__ = smalloc(sizeof(*__new_cb__)); \
185     __new_cb__->func = funca; \
186     __new_cb__->data = dataa; \
187     __new_cb__->prev = NULL; \
188     __new_cb__->next = name; \
189     if(name != NULL) { \
190         name->prev = __new_cb__; \
191     } \
192     name = __new_cb__; \
193 } while(0)
194
195 #define CBCHAININIT(obj, name) (obj)->name = NULL
196
197 #define CBCHAINFREE(obj, name) \
198 do { \
199     struct cbchain_ ## name *__cur__; \
200     while((__cur__ = (obj)->name) != NULL) { \
201         (obj)->name = __cur__->next; \
202         if(__cur__->destroy != NULL) \
203             __cur__->destroy(__cur__->data); \
204         free(__cur__); \
205     } \
206 } while(0)
207
208 #define CBCHAINDOCB(obj, name, args...) \
209 do { \
210     struct cbchain_ ## name *__cur__, *__next__; \
211     for(__cur__ = (obj)->name; __cur__ != NULL; __cur__ = __next__) { \
212         __next__ = __cur__->next; \
213         if(__cur__->func(args, __cur__->data)) { \
214             if(__cur__->next != NULL) \
215                 __cur__->next->prev = __cur__->prev; \
216             if(__cur__->prev != NULL) \
217                 __cur__->prev->next = __cur__->next; \
218             if(__cur__ == (obj)->name) \
219                 (obj)->name = __cur__->next; \
220             free(__cur__); \
221         } \
222     } \
223 } while(0)
224
225 #define GCBCHAINDOCB(name, args...) \
226 ({ \
227     struct cbchain_ ## name *__cur__; \
228     int __ret__; \
229     __ret__ = 0; \
230     for(__cur__ = name; __cur__ != NULL; __cur__ = __cur__->next) { \
231         if(__cur__->func(args, __cur__->data)) { \
232             __ret__ = 1; \
233             break; \
234         } \
235     } \
236     __ret__; \
237 })
238
239 #endif