Add support for Solaris/x86 (bug #3064)
[asterisk/asterisk.git] / include / asterisk / utils.h
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Utility functions
5  *
6  * Copyright (C) 2004 - 2005, Digium, Inc.
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #ifndef _ASTERISK_UTIL_H
13 #define _ASTERISK_UTIL_H
14
15 #ifdef SOLARIS
16 #include <solaris-compat/compat.h>
17 #endif
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <pthread.h>
21 #include <asterisk/lock.h>
22 #include <limits.h>
23
24 /* Note:
25    It is very important to use only unsigned variables to hold
26    bit flags, as otherwise you can fall prey to the compiler's
27    sign-extension antics if you try to use the top two bits in
28    your variable.
29
30    The flag macros below use a set of compiler tricks to verify
31    that the caller is using an "unsigned int" variable to hold
32    the flags, and nothing else. If the caller uses any other
33    type of variable, a warning message similar to this:
34
35    warning: comparison of distinct pointer types lacks cast
36
37    will be generated.
38
39    The "dummy" variable below is used to make these comparisons.
40
41    Also note that at -O2 or above, this type-safety checking
42    does _not_ produce any additional object code at all.
43 */
44
45 extern unsigned int __unsigned_int_flags_dummy;
46
47 #define ast_test_flag(p,flag)           ({ \
48                                         typeof ((p)->flags) __p = (p)->flags; \
49                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
50                                         (void) (&__p == &__x); \
51                                         ((p)->flags & (flag)); \
52                                         })
53
54 #define ast_set_flag(p,flag)            do { \
55                                         typeof ((p)->flags) __p = (p)->flags; \
56                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
57                                         (void) (&__p == &__x); \
58                                         ((p)->flags |= (flag)); \
59                                         } while(0)
60
61 #define ast_clear_flag(p,flag)          do { \
62                                         typeof ((p)->flags) __p = (p)->flags; \
63                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
64                                         (void) (&__p == &__x); \
65                                         ((p)->flags &= ~(flag)); \
66                                         } while(0)
67
68 #define ast_copy_flags(dest,src,flagz)  do { \
69                                         typeof ((dest)->flags) __d = (dest)->flags; \
70                                         typeof ((src)->flags) __s = (src)->flags; \
71                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
72                                         (void) (&__d == &__x); \
73                                         (void) (&__s == &__x); \
74                                         (dest)->flags &= ~(flagz); \
75                                         (dest)->flags |= ((src)->flags & (flagz)); \
76                                         } while (0)
77
78 #define ast_set2_flag(p,value,flag)     do { \
79                                         typeof ((p)->flags) __p = (p)->flags; \
80                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
81                                         (void) (&__p == &__x); \
82                                         if (value) \
83                                                 (p)->flags |= (flag); \
84                                         else \
85                                                 (p)->flags &= ~(flag); \
86                                         } while (0)
87
88 /* Non-type checking variations for non-unsigned int flags.  You
89    should only use non-unsigned int flags where required by 
90    protocol etc and if you know what you're doing :)  */
91 #define ast_test_flag_nonstd(p,flag)            ({ \
92                                         ((p)->flags & (flag)); \
93                                         })
94
95 #define ast_set_flag_nonstd(p,flag)             do { \
96                                         ((p)->flags |= (flag)); \
97                                         } while(0)
98
99 #define ast_clear_flag_nonstd(p,flag)           do { \
100                                         ((p)->flags &= ~(flag)); \
101                                         } while(0)
102
103 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
104                                         (dest)->flags &= ~(flagz); \
105                                         (dest)->flags |= ((src)->flags & (flagz)); \
106                                         } while (0)
107
108 #define ast_set2_flag_nonstd(p,value,flag)      do { \
109                                         if (value) \
110                                                 (p)->flags |= (flag); \
111                                         else \
112                                                 (p)->flags &= ~(flag); \
113                                         } while (0)
114
115 #define AST_FLAGS_ALL UINT_MAX
116
117 struct ast_flags {
118         unsigned int flags;
119 };
120
121 static inline int ast_strlen_zero(const char *s)
122 {
123         return (*s == '\0');
124 }
125
126 struct ast_hostent {
127         struct hostent hp;
128         char buf[1024];
129 };
130
131 extern char *ast_strip(char *buf);
132 extern struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
133 /* ast_md5_hash: Produces MD5 hash based on input string */
134 extern void ast_md5_hash(char *output, char *input);
135 extern int ast_base64encode(char *dst, unsigned char *src, int srclen, int max);
136 extern int ast_base64decode(unsigned char *dst, char *src, int max);
137
138 extern int test_for_thread_safety(void);
139
140 extern const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia);
141 extern int ast_utils_init(void);
142 extern int ast_wait_for_input(int fd, int ms);
143
144 /* The realloca lets us ast_restrdupa(), but you can't mix any other ast_strdup calls! */
145
146 struct ast_realloca {
147         char *ptr;
148         int alloclen;
149 };
150
151 #define ast_restrdupa(ra, s) \
152         ({ \
153                 if ((ra)->ptr && strlen(s) + 1 < (ra)->alloclen) { \
154                         strcpy((ra)->ptr, s); \
155                 } else { \
156                         (ra)->ptr = alloca(strlen(s) + 1 - (ra)->alloclen); \
157                         if ((ra)->ptr) (ra)->alloclen = strlen(s) + 1; \
158                 } \
159                 (ra)->ptr; \
160         })
161
162 #ifdef inet_ntoa
163 #undef inet_ntoa
164 #endif
165 #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__
166
167 #define AST_STACKSIZE 256 * 1024
168 #define ast_pthread_create(a,b,c,d) ast_pthread_create_stack(a,b,c,d,0)
169 #ifdef __linux__
170 #define ast_strcasestr strcasestr
171 #else
172 extern char *ast_strcasestr(const char *, const char *);
173 #endif /* __linux__ */
174 extern int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize);
175 #endif