Various cleanups from comments in an email from Luigi Rizzo. Thank you!
[asterisk/asterisk.git] / include / asterisk / utils.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  * \brief Utility functions
21  */
22
23 #ifndef _ASTERISK_UTILS_H
24 #define _ASTERISK_UTILS_H
25
26 #include "asterisk/compat.h"
27
28 #include <stdlib.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>  /* we want to override inet_ntoa */
31 #include <netdb.h>
32 #include <limits.h>
33
34 #include "asterisk/lock.h"
35 #include "asterisk/time.h"
36 #include "asterisk/strings.h"
37 #include "asterisk/logger.h"
38
39 /*! \note
40  \verbatim
41    Note:
42    It is very important to use only unsigned variables to hold
43    bit flags, as otherwise you can fall prey to the compiler's
44    sign-extension antics if you try to use the top two bits in
45    your variable.
46
47    The flag macros below use a set of compiler tricks to verify
48    that the caller is using an "unsigned int" variable to hold
49    the flags, and nothing else. If the caller uses any other
50    type of variable, a warning message similar to this:
51
52    warning: comparison of distinct pointer types lacks cast
53    will be generated.
54
55    The "dummy" variable below is used to make these comparisons.
56
57    Also note that at -O2 or above, this type-safety checking
58    does _not_ produce any additional object code at all.
59  \endverbatim
60 */
61
62 extern unsigned int __unsigned_int_flags_dummy;
63
64 #define ast_test_flag(p,flag)           ({ \
65                                         typeof ((p)->flags) __p = (p)->flags; \
66                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
67                                         (void) (&__p == &__x); \
68                                         ((p)->flags & (flag)); \
69                                         })
70
71 #define ast_set_flag(p,flag)            do { \
72                                         typeof ((p)->flags) __p = (p)->flags; \
73                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
74                                         (void) (&__p == &__x); \
75                                         ((p)->flags |= (flag)); \
76                                         } while(0)
77
78 #define ast_clear_flag(p,flag)          do { \
79                                         typeof ((p)->flags) __p = (p)->flags; \
80                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
81                                         (void) (&__p == &__x); \
82                                         ((p)->flags &= ~(flag)); \
83                                         } while(0)
84
85 #define ast_copy_flags(dest,src,flagz)  do { \
86                                         typeof ((dest)->flags) __d = (dest)->flags; \
87                                         typeof ((src)->flags) __s = (src)->flags; \
88                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
89                                         (void) (&__d == &__x); \
90                                         (void) (&__s == &__x); \
91                                         (dest)->flags &= ~(flagz); \
92                                         (dest)->flags |= ((src)->flags & (flagz)); \
93                                         } while (0)
94
95 #define ast_set2_flag(p,value,flag)     do { \
96                                         typeof ((p)->flags) __p = (p)->flags; \
97                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
98                                         (void) (&__p == &__x); \
99                                         if (value) \
100                                                 (p)->flags |= (flag); \
101                                         else \
102                                                 (p)->flags &= ~(flag); \
103                                         } while (0)
104
105 /* Non-type checking variations for non-unsigned int flags.  You
106    should only use non-unsigned int flags where required by 
107    protocol etc and if you know what you're doing :)  */
108 #define ast_test_flag_nonstd(p,flag)            ({ \
109                                         ((p)->flags & (flag)); \
110                                         })
111
112 #define ast_set_flag_nonstd(p,flag)             do { \
113                                         ((p)->flags |= (flag)); \
114                                         } while(0)
115
116 #define ast_clear_flag_nonstd(p,flag)           do { \
117                                         ((p)->flags &= ~(flag)); \
118                                         } while(0)
119
120 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
121                                         (dest)->flags &= ~(flagz); \
122                                         (dest)->flags |= ((src)->flags & (flagz)); \
123                                         } while (0)
124
125 #define ast_set2_flag_nonstd(p,value,flag)      do { \
126                                         if (value) \
127                                                 (p)->flags |= (flag); \
128                                         else \
129                                                 (p)->flags &= ~(flag); \
130                                         } while (0)
131
132 #define AST_FLAGS_ALL UINT_MAX
133
134 struct ast_flags {
135         unsigned int flags;
136 };
137
138 struct ast_hostent {
139         struct hostent hp;
140         char buf[1024];
141 };
142
143 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
144
145 /* ast_md5_hash 
146         \brief Produces MD5 hash based on input string */
147 void ast_md5_hash(char *output, char *input);
148
149 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
150 int ast_base64decode(unsigned char *dst, const char *src, int max);
151
152 /*! ast_uri_encode
153         \brief Turn text string to URI-encoded %XX version 
154         At this point, we're converting from ISO-8859-x (8-bit), not UTF8
155         as in the SIP protocol spec 
156         If doreserved == 1 we will convert reserved characters also.
157         RFC 2396, section 2.4
158         outbuf needs to have more memory allocated than the instring
159         to have room for the expansion. Every char that is converted
160         is replaced by three ASCII characters.
161         \param string   String to be converted
162         \param outbuf   Resulting encoded string
163         \param buflen   Size of output buffer
164         \param doreserved       Convert reserved characters
165 */
166
167 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
168
169 /*!     \brief Decode URI, URN, URL (overwrite string)
170         \param s        String to be decoded 
171  */
172 void ast_uri_decode(char *s);
173
174 static force_inline void ast_slinear_saturated_add(short *input, short *value)
175 {
176         int res;
177
178         res = (int) *input + *value;
179         if (res > 32767)
180                 *input = 32767;
181         else if (res < -32767)
182                 *input = -32767;
183         else
184                 *input = (short) res;
185 }
186         
187 static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
188 {
189         int res;
190
191         res = (int) *input * *value;
192         if (res > 32767)
193                 *input = 32767;
194         else if (res < -32767)
195                 *input = -32767;
196         else
197                 *input = (short) res;
198 }
199
200 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
201 {
202         *input /= *value;
203 }
204
205 int test_for_thread_safety(void);
206
207 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia);
208
209 #ifdef inet_ntoa
210 #undef inet_ntoa
211 #endif
212 #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__
213
214 int ast_utils_init(void);
215 int ast_wait_for_input(int fd, int ms);
216
217 /*! Compares the source address and port of two sockaddr_in */
218 static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
219 {
220         return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) 
221                 || (sin1->sin_port != sin2->sin_port));
222 }
223
224 #define AST_STACKSIZE 256 * 1024
225 #define ast_pthread_create(a,b,c,d) ast_pthread_create_stack(a,b,c,d,0)
226 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize);
227
228 /*!
229         \brief Process a string to find and replace characters
230         \param start The string to analyze
231         \param find The character to find
232         \param replace_with The character that will replace the one we are looking for
233 */
234 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
235
236 #ifndef HAVE_GETLOADAVG
237 int getloadavg(double *list, int nelem);
238 #endif
239
240 #ifdef linux
241 #define ast_random random
242 #else
243 long int ast_random(void);
244 #endif
245
246 /*!
247   \brief A wrapper for malloc()
248
249   ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
250   message in the case that the allocation fails.
251
252   The argument and return value are the same as malloc()
253 */
254 #define ast_malloc(len) \
255         _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
256
257 AST_INLINE_API(
258 void *_ast_malloc(size_t len, const char *file, int lineno, const char *func),
259 {
260         void *p;
261
262         p = malloc(len);
263
264         if (!p)
265                 ast_log(LOG_ERROR, "Memory Allocation Failure - '%d' bytes in function %s at line %d of %s\n", (int)len, func, lineno, file);
266
267         return p;
268 }
269 )
270
271 /*!
272   \brief A wrapper for calloc()
273
274   ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
275   message in the case that the allocation fails.
276
277   The arguments and return value are the same as calloc()
278 */
279 #define ast_calloc(num, len) \
280         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
281
282 AST_INLINE_API(
283 void *_ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
284 {
285         void *p;
286
287         p = calloc(num, len);
288
289         if (!p)
290                 ast_log(LOG_ERROR, "Memory Allocation Failure - '%d' bytes in function %s at line %d of %s\n", (int)len, func, lineno, file);
291
292         return p;
293 }
294 )
295
296 /*!
297   \brief A wrapper for realloc()
298
299   ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
300   message in the case that the allocation fails.
301
302   The arguments and return value are the same as realloc()
303 */
304 #define ast_realloc(p, len) \
305         _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
306
307 AST_INLINE_API(
308 void *_ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
309 {
310         void *newp;
311
312         newp = realloc(p, len);
313
314         if (!newp)
315                 ast_log(LOG_ERROR, "Memory Allocation Failure - '%d' bytes in function %s at line %d of %s\n", (int)len, func, lineno, file);
316
317         return newp;
318 }
319 )
320
321 /*!
322   \brief A wrapper for strdup()
323
324   ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
325   message in the case that the allocation fails.
326
327   ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
328   argument is provided, ast_strdup will return NULL without generating any
329   kind of error log message.
330
331   The argument and return value are the same as strdup()
332 */
333 #define ast_strdup(str) \
334         _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
335
336 AST_INLINE_API(
337 char *_ast_strdup(const char *str, const char *file, int lineno, const char *func),
338 {
339         char *newstr = NULL;
340
341         if (str) {
342                 newstr = strdup(str);
343
344                 if (!newstr)
345                         ast_log(LOG_ERROR, "Memory Allocation Failure - Could not duplicate '%s' in function %s at line %d of %s\n", str, func, lineno, file);
346         }
347
348         return newstr;
349 }
350 )
351
352 /*!
353   \brief A wrapper for strndup()
354
355   ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
356   message in the case that the allocation fails.
357
358   ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
359   string to duplicate. If a NULL argument is provided, ast_strdup will return  
360   NULL without generating any kind of error log message.
361
362   The arguments and return value are the same as strndup()
363 */
364 #define ast_strndup(str, len) \
365         _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
366
367 AST_INLINE_API(
368 char *_ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
369 {
370         char *newstr = NULL;
371
372         if (str) {
373                 newstr = strndup(str, len);
374
375                 if (!newstr)
376                         ast_log(LOG_ERROR, "Memory Allocation Failure - Could not duplicate '%d' bytes of '%s' in function %s at line %d of %s\n", (int)len, str, func, lineno, file);
377         }
378
379         return newstr;
380 }
381 )
382
383 #endif /* _ASTERISK_UTILS_H */