Make the MALLOC_DEBUG output for free() useful again. After changing calls to
[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 <stdio.h>
30 #include <stdarg.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>  /* we want to override inet_ntoa */
33 #include <netdb.h>
34 #include <limits.h>
35 #include <string.h>
36 #include <time.h>       /* we want to override localtime_r */
37
38 #include "asterisk/lock.h"
39 #include "asterisk/time.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/compiler.h"
42 #include "asterisk/localtime.h"
43
44 /*! 
45 \note \verbatim
46    Note:
47    It is very important to use only unsigned variables to hold
48    bit flags, as otherwise you can fall prey to the compiler's
49    sign-extension antics if you try to use the top two bits in
50    your variable.
51
52    The flag macros below use a set of compiler tricks to verify
53    that the caller is using an "unsigned int" variable to hold
54    the flags, and nothing else. If the caller uses any other
55    type of variable, a warning message similar to this:
56
57    warning: comparison of distinct pointer types lacks cast
58    will be generated.
59
60    The "dummy" variable below is used to make these comparisons.
61
62    Also note that at -O2 or above, this type-safety checking
63    does _not_ produce any additional object code at all.
64  \endverbatim
65 */
66
67 extern unsigned int __unsigned_int_flags_dummy;
68
69 #define ast_test_flag(p,flag)           ({ \
70                                         typeof ((p)->flags) __p = (p)->flags; \
71                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
72                                         (void) (&__p == &__x); \
73                                         ((p)->flags & (flag)); \
74                                         })
75
76 #define ast_set_flag(p,flag)            do { \
77                                         typeof ((p)->flags) __p = (p)->flags; \
78                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
79                                         (void) (&__p == &__x); \
80                                         ((p)->flags |= (flag)); \
81                                         } while(0)
82
83 #define ast_clear_flag(p,flag)          do { \
84                                         typeof ((p)->flags) __p = (p)->flags; \
85                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
86                                         (void) (&__p == &__x); \
87                                         ((p)->flags &= ~(flag)); \
88                                         } while(0)
89
90 #define ast_copy_flags(dest,src,flagz)  do { \
91                                         typeof ((dest)->flags) __d = (dest)->flags; \
92                                         typeof ((src)->flags) __s = (src)->flags; \
93                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
94                                         (void) (&__d == &__x); \
95                                         (void) (&__s == &__x); \
96                                         (dest)->flags &= ~(flagz); \
97                                         (dest)->flags |= ((src)->flags & (flagz)); \
98                                         } while (0)
99
100 #define ast_set2_flag(p,value,flag)     do { \
101                                         typeof ((p)->flags) __p = (p)->flags; \
102                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
103                                         (void) (&__p == &__x); \
104                                         if (value) \
105                                                 (p)->flags |= (flag); \
106                                         else \
107                                                 (p)->flags &= ~(flag); \
108                                         } while (0)
109
110 #define ast_set_flags_to(p,flag,value)  do { \
111                                         typeof ((p)->flags) __p = (p)->flags; \
112                                         typeof (__unsigned_int_flags_dummy) __x = 0; \
113                                         (void) (&__p == &__x); \
114                                         (p)->flags &= ~(flag); \
115                                         (p)->flags |= (value); \
116                                         } while (0)
117
118
119 /* The following 64-bit flag code can most likely be erased after app_dial
120    is reorganized to either reduce the large number of options, or handle
121    them in some other way. At the time of this writing, app_dial would be
122    the only user of 64-bit option flags */
123
124 extern uint64_t __unsigned_int_flags_dummy64;
125
126 #define ast_test_flag64(p,flag)                 ({ \
127                                         typeof ((p)->flags) __p = (p)->flags; \
128                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
129                                         (void) (&__p == &__x); \
130                                         ((p)->flags & (flag)); \
131                                         })
132
133 #define ast_set_flag64(p,flag)          do { \
134                                         typeof ((p)->flags) __p = (p)->flags; \
135                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
136                                         (void) (&__p == &__x); \
137                                         ((p)->flags |= (flag)); \
138                                         } while(0)
139
140 #define ast_clear_flag64(p,flag)                do { \
141                                         typeof ((p)->flags) __p = (p)->flags; \
142                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
143                                         (void) (&__p == &__x); \
144                                         ((p)->flags &= ~(flag)); \
145                                         } while(0)
146
147 #define ast_copy_flags64(dest,src,flagz)        do { \
148                                         typeof ((dest)->flags) __d = (dest)->flags; \
149                                         typeof ((src)->flags) __s = (src)->flags; \
150                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
151                                         (void) (&__d == &__x); \
152                                         (void) (&__s == &__x); \
153                                         (dest)->flags &= ~(flagz); \
154                                         (dest)->flags |= ((src)->flags & (flagz)); \
155                                         } while (0)
156
157 #define ast_set2_flag64(p,value,flag)   do { \
158                                         typeof ((p)->flags) __p = (p)->flags; \
159                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
160                                         (void) (&__p == &__x); \
161                                         if (value) \
162                                                 (p)->flags |= (flag); \
163                                         else \
164                                                 (p)->flags &= ~(flag); \
165                                         } while (0)
166
167 #define ast_set_flags_to64(p,flag,value)        do { \
168                                         typeof ((p)->flags) __p = (p)->flags; \
169                                         typeof (__unsigned_int_flags_dummy64) __x = 0; \
170                                         (void) (&__p == &__x); \
171                                         (p)->flags &= ~(flag); \
172                                         (p)->flags |= (value); \
173                                         } while (0)
174
175
176 /* Non-type checking variations for non-unsigned int flags.  You
177    should only use non-unsigned int flags where required by 
178    protocol etc and if you know what you're doing :)  */
179 #define ast_test_flag_nonstd(p,flag) \
180                                         ((p)->flags & (flag))
181
182 #define ast_set_flag_nonstd(p,flag)             do { \
183                                         ((p)->flags |= (flag)); \
184                                         } while(0)
185
186 #define ast_clear_flag_nonstd(p,flag)           do { \
187                                         ((p)->flags &= ~(flag)); \
188                                         } while(0)
189
190 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
191                                         (dest)->flags &= ~(flagz); \
192                                         (dest)->flags |= ((src)->flags & (flagz)); \
193                                         } while (0)
194
195 #define ast_set2_flag_nonstd(p,value,flag)      do { \
196                                         if (value) \
197                                                 (p)->flags |= (flag); \
198                                         else \
199                                                 (p)->flags &= ~(flag); \
200                                         } while (0)
201
202 #define AST_FLAGS_ALL UINT_MAX
203
204 /*! \brief Structure used to handle boolean flags 
205 */
206 struct ast_flags {
207         unsigned int flags;
208 };
209
210 /*! \brief Structure used to handle a large number of boolean flags == used only in app_dial?
211 */
212 struct ast_flags64 {
213         uint64_t flags;
214 };
215
216 struct ast_hostent {
217         struct hostent hp;
218         char buf[1024];
219 };
220
221 /*! \brief Thread-safe gethostbyname function to use in Asterisk */
222 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
223
224 /*!  \brief Produces MD5 hash based on input string */
225 void ast_md5_hash(char *output, char *input);
226 /*! \brief Produces SHA1 hash based on input string */
227 void ast_sha1_hash(char *output, char *input);
228
229 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);
230
231 /*!
232  * \brief Encode data in base64
233  * \param dst the destination buffer
234  * \param src the source data to be encoded
235  * \param srclen the number of bytes present in the source buffer
236  * \param max the maximum number of bytes to write into the destination
237  *        buffer, *including* the terminating NULL character.
238  */
239 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
240
241 /*!
242  * \brief Decode data from base64
243  * \param dst the destination buffer
244  * \param src the source buffer
245  * \param max The maximum number of bytes to write into the destination
246  *            buffer.  Note that this function will not ensure that the
247  *            destination buffer is NULL terminated.  So, in general,
248  *            this parameter should be sizeof(dst) - 1.
249  */
250 int ast_base64decode(unsigned char *dst, const char *src, int max);
251
252 /*!  \brief Turn text string to URI-encoded %XX version 
253
254 \note   At this point, we're converting from ISO-8859-x (8-bit), not UTF8
255         as in the SIP protocol spec 
256         If doreserved == 1 we will convert reserved characters also.
257         RFC 2396, section 2.4
258         outbuf needs to have more memory allocated than the instring
259         to have room for the expansion. Every char that is converted
260         is replaced by three ASCII characters.
261         \param string   String to be converted
262         \param outbuf   Resulting encoded string
263         \param buflen   Size of output buffer
264         \param doreserved       Convert reserved characters
265 */
266
267 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
268
269 /*!     \brief Decode URI, URN, URL (overwrite string)
270         \param s        String to be decoded 
271  */
272 void ast_uri_decode(char *s);
273
274 static force_inline void ast_slinear_saturated_add(short *input, short *value)
275 {
276         int res;
277
278         res = (int) *input + *value;
279         if (res > 32767)
280                 *input = 32767;
281         else if (res < -32767)
282                 *input = -32767;
283         else
284                 *input = (short) res;
285 }
286
287 static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
288 {
289         int res;
290
291         res = (int) *input - *value;
292         if (res > 32767)
293                 *input = 32767;
294         else if (res < -32767)
295                 *input = -32767;
296         else
297                 *input = (short) res;
298 }
299         
300 static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
301 {
302         int res;
303
304         res = (int) *input * *value;
305         if (res > 32767)
306                 *input = 32767;
307         else if (res < -32767)
308                 *input = -32767;
309         else
310                 *input = (short) res;
311 }
312
313 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
314 {
315         *input /= *value;
316 }
317
318 int test_for_thread_safety(void);
319
320 /*!
321  * \brief thread-safe replacement for inet_ntoa().
322  *
323  * \note It is very important to note that even though this is a thread-safe
324  *       replacement for inet_ntoa(), it is *not* reentrant.  In a single
325  *       thread, the result from a previous call to this function is no longer
326  *       valid once it is called again.  If the result from multiple calls to
327  *       this function need to be kept or used at once, then the result must be
328  *       copied to a local buffer before calling this function again.
329  */
330 const char *ast_inet_ntoa(struct in_addr ia);
331
332 #ifdef inet_ntoa
333 #undef inet_ntoa
334 #endif
335 #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__
336
337 #ifdef localtime_r
338 #undef localtime_r
339 #endif
340 #define localtime_r __dont_use_localtime_r_use_ast_localtime_instead__
341
342 int ast_utils_init(void);
343 int ast_wait_for_input(int fd, int ms);
344
345 /*!
346         \brief Try to write string, but wait no more than ms milliseconds
347         before timing out.
348
349         \note If you are calling ast_carefulwrite, it is assumed that you are calling
350         it on a file descriptor that _DOES_ have NONBLOCK set.  This way,
351         there is only one system call made to do a write, unless we actually
352         have a need to wait.  This way, we get better performance.
353 */
354 int ast_carefulwrite(int fd, char *s, int len, int timeoutms);
355
356 /*! \brief Compares the source address and port of two sockaddr_in */
357 static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
358 {
359         return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) 
360                 || (sin1->sin_port != sin2->sin_port));
361 }
362
363 #define AST_STACKSIZE 240 * 1024
364
365 #if defined(LOW_MEMORY)
366 #define AST_BACKGROUND_STACKSIZE 48 * 1024
367 #else
368 #define AST_BACKGROUND_STACKSIZE 240 * 1024
369 #endif
370
371 void ast_register_thread(char *name);
372 void ast_unregister_thread(void *id);
373
374 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
375                              void *data, size_t stacksize, const char *file, const char *caller,
376                              int line, const char *start_fn);
377
378 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void *),
379                                  void *data, size_t stacksize, const char *file, const char *caller,
380                                  int line, const char *start_fn);
381
382 #define ast_pthread_create(a, b, c, d) ast_pthread_create_stack(a, b, c, d,                     \
383                                                                 0,                              \
384                                                                 __FILE__, __FUNCTION__,         \
385                                                                 __LINE__, #c)
386 #define ast_pthread_create_detached(a, b, c, d) ast_pthread_create_detached_stack(a, b, c, d, \
387                                                                         0, \
388                                                                         __FILE__, __FUNCTION__, \
389                                                                         __LINE__, #c)
390
391 #define ast_pthread_create_background(a, b, c, d) ast_pthread_create_stack(a, b, c, d,                  \
392                                                                            AST_BACKGROUND_STACKSIZE,    \
393                                                                            __FILE__, __FUNCTION__,      \
394                                                                            __LINE__, #c)
395
396 #define ast_pthread_create_detached_background(a, b, c, d) ast_pthread_create_detached_stack(a, b, c, d, \
397                                                                         AST_BACKGROUND_STACKSIZE, \
398                                                                         __FILE__, __FUNCTION__, \
399                                                                         __LINE__, #c)
400
401 /*!
402         \brief Process a string to find and replace characters
403         \param start The string to analyze
404         \param find The character to find
405         \param replace_with The character that will replace the one we are looking for
406 */
407 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
408
409 long int ast_random(void);
410
411 #define ast_free free
412
413 /*! 
414  * \brief free() wrapper
415  *
416  * ast_free_ptr should be used when a function pointer for free() needs to be passed
417  * as the argument to a function. Otherwise, astmm will cause seg faults.
418  */
419 #ifdef __AST_DEBUG_MALLOC
420 static void ast_free_ptr(void *ptr) attribute_unused;
421 static void ast_free_ptr(void *ptr)
422 {
423         ast_free(ptr);
424 }
425 #else
426 #define ast_free_ptr ast_free
427 #endif
428
429 #ifndef __AST_DEBUG_MALLOC
430
431 #define MALLOC_FAILURE_MSG \
432         ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
433 /*!
434  * \brief A wrapper for malloc()
435  *
436  * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
437  * message in the case that the allocation fails.
438  *
439  * The argument and return value are the same as malloc()
440  */
441 #define ast_malloc(len) \
442         _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
443
444 AST_INLINE_API(
445 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
446 {
447         void *p;
448
449         if (!(p = malloc(len)))
450                 MALLOC_FAILURE_MSG;
451
452         return p;
453 }
454 )
455
456 /*!
457  * \brief A wrapper for calloc()
458  *
459  * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
460  * message in the case that the allocation fails.
461  *
462  * The arguments and return value are the same as calloc()
463  */
464 #define ast_calloc(num, len) \
465         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
466
467 AST_INLINE_API(
468 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
469 {
470         void *p;
471
472         if (!(p = calloc(num, len)))
473                 MALLOC_FAILURE_MSG;
474
475         return p;
476 }
477 )
478
479 /*!
480  * \brief A wrapper for calloc() for use in cache pools
481  *
482  * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
483  * message in the case that the allocation fails. When memory debugging is in use,
484  * the memory allocated by this function will be marked as 'cache' so it can be
485  * distinguished from normal memory allocations.
486  *
487  * The arguments and return value are the same as calloc()
488  */
489 #define ast_calloc_cache(num, len) \
490         _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
491
492 /*!
493  * \brief A wrapper for realloc()
494  *
495  * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
496  * message in the case that the allocation fails.
497  *
498  * The arguments and return value are the same as realloc()
499  */
500 #define ast_realloc(p, len) \
501         _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
502
503 AST_INLINE_API(
504 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
505 {
506         void *newp;
507
508         if (!(newp = realloc(p, len)))
509                 MALLOC_FAILURE_MSG;
510
511         return newp;
512 }
513 )
514
515 /*!
516  * \brief A wrapper for strdup()
517  *
518  * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
519  * message in the case that the allocation fails.
520  *
521  * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
522  * argument is provided, ast_strdup will return NULL without generating any
523  * kind of error log message.
524  *
525  * The argument and return value are the same as strdup()
526  */
527 #define ast_strdup(str) \
528         _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
529
530 AST_INLINE_API(
531 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
532 {
533         char *newstr = NULL;
534
535         if (str) {
536                 if (!(newstr = strdup(str)))
537                         MALLOC_FAILURE_MSG;
538         }
539
540         return newstr;
541 }
542 )
543
544 /*!
545  * \brief A wrapper for strndup()
546  *
547  * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
548  * message in the case that the allocation fails.
549  *
550  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
551  * string to duplicate. If a NULL argument is provided, ast_strdup will return  
552  * NULL without generating any kind of error log message.
553  *
554  * The arguments and return value are the same as strndup()
555  */
556 #define ast_strndup(str, len) \
557         _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
558
559 AST_INLINE_API(
560 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
561 {
562         char *newstr = NULL;
563
564         if (str) {
565                 if (!(newstr = strndup(str, len)))
566                         MALLOC_FAILURE_MSG;
567         }
568
569         return newstr;
570 }
571 )
572
573 /*!
574  * \brief A wrapper for asprintf()
575  *
576  * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
577  * message in the case that the allocation fails.
578  *
579  * The arguments and return value are the same as asprintf()
580  */
581 #define ast_asprintf(ret, fmt, ...) \
582         _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
583
584 AST_INLINE_API(
585 int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...),
586 {
587         int res;
588         va_list ap;
589
590         va_start(ap, fmt);
591         if ((res = vasprintf(ret, fmt, ap)) == -1)
592                 MALLOC_FAILURE_MSG;
593         va_end(ap);
594
595         return res;
596 }
597 )
598
599 /*!
600  * \brief A wrapper for vasprintf()
601  *
602  * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
603  * message in the case that the allocation fails.
604  *
605  * The arguments and return value are the same as vasprintf()
606  */
607 #define ast_vasprintf(ret, fmt, ap) \
608         _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
609
610 AST_INLINE_API(
611 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
612 {
613         int res;
614
615         if ((res = vasprintf(ret, fmt, ap)) == -1)
616                 MALLOC_FAILURE_MSG;
617
618         return res;
619 }
620 )
621
622 #else
623
624 /* If astmm is in use, let it handle these.  Otherwise, it will report that
625    all allocations are coming from this header file */
626
627 #define ast_malloc(a)           malloc(a)
628 #define ast_calloc(a,b)         calloc(a,b)
629 #define ast_realloc(a,b)        realloc(a,b)
630 #define ast_strdup(a)           strdup(a)
631 #define ast_strndup(a,b)        strndup(a,b)
632 #define ast_asprintf(a,b,c)     asprintf(a,b,c)
633 #define ast_vasprintf(a,b,c)    vasprintf(a,b,c)
634
635 #endif /* AST_DEBUG_MALLOC */
636
637 #if !defined(ast_strdupa) && defined(__GNUC__)
638 /*!
639   \brief duplicate a string in memory from the stack
640   \param s The string to duplicate
641
642   This macro will duplicate the given string.  It returns a pointer to the stack
643   allocatted memory for the new string.
644 */
645 #define ast_strdupa(s)                                                    \
646         (__extension__                                                    \
647         ({                                                                \
648                 const char *__old = (s);                                  \
649                 size_t __len = strlen(__old) + 1;                         \
650                 char *__new = __builtin_alloca(__len);                    \
651                 memcpy (__new, __old, __len);                             \
652                 __new;                                                    \
653         }))
654 #endif
655
656 /*!
657   \brief Disable PMTU discovery on a socket
658   \param sock The socket to manipulate
659   \return Nothing
660
661   On Linux, UDP sockets default to sending packets with the Dont Fragment (DF)
662   bit set. This is supposedly done to allow the application to do PMTU
663   discovery, but Asterisk does not do this.
664
665   Because of this, UDP packets sent by Asterisk that are larger than the MTU
666   of any hop in the path will be lost. This function can be called on a socket
667   to ensure that the DF bit will not be set.
668  */
669 void ast_enable_packet_fragmentation(int sock);
670
671 /*!
672   \brief Recursively create directory path
673   \param path The directory path to create
674   \param mode The permissions with which to try to create the directory
675   \return 0 on success or an error code otherwise
676
677   Creates a directory path, creating parent directories as needed.
678  */
679 int ast_mkdir(const char *path, int mode);
680
681 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
682
683 #include "asterisk/strings.h"
684
685 #endif /* _ASTERISK_UTILS_H */