📄 strings.h
字号:
*/AST_INLINE_API(struct ast_str * attribute_malloc ast_str_create(size_t init_len),{ struct ast_str *buf; buf = (struct ast_str *)ast_calloc(1, sizeof(*buf) + init_len); if (buf == NULL) return NULL; buf->len = init_len; buf->used = 0; buf->ts = DS_MALLOC; return buf;})/*! \brief Reset the content of a dynamic string. * Useful before a series of ast_str_append. */AST_INLINE_API(void ast_str_reset(struct ast_str *buf),{ if (buf) { buf->used = 0; if (buf->len) buf->str[0] = '\0'; }})/* * AST_INLINE_API() is a macro that takes a block of code as an argument. * Using preprocessor #directives in the argument is not supported by all * compilers, and it is a bit of an obfuscation anyways, so avoid it. * As a workaround, define a macro that produces either its argument * or nothing, and use that instead of #ifdef/#endif within the * argument to AST_INLINE_API(). */#if defined(DEBUG_THREADLOCALS)#define _DB1(x) x#else#define _DB1(x)#endif/*! * Make space in a new string (e.g. to read in data from a file) */AST_INLINE_API(int ast_str_make_space(struct ast_str **buf, size_t new_len),{ _DB1(struct ast_str *old_buf = *buf;) if (new_len <= (*buf)->len) return 0; /* success */ if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC) return -1; /* cannot extend */ *buf = (struct ast_str *)ast_realloc(*buf, new_len + sizeof(struct ast_str)); if (*buf == NULL) /* XXX watch out, we leak memory here */ return -1; if ((*buf)->ts != DS_MALLOC) { pthread_setspecific((*buf)->ts->key, *buf); _DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));) } (*buf)->len = new_len; return 0;})#define ast_str_alloca(init_len) \ ({ \ struct ast_str *buf; \ buf = alloca(sizeof(*buf) + init_len); \ buf->len = init_len; \ buf->used = 0; \ buf->ts = DS_ALLOCA; \ buf->str[0] = '\0'; \ (buf); \ })/*! * \brief Retrieve a thread locally stored dynamic string * * \arg ts This is a pointer to the thread storage structure declared by using * the AST_THREADSTORAGE macro. If declared with * AST_THREADSTORAGE(my_buf, my_buf_init), then this argument would be * (&my_buf). * \arg init_len This is the initial length of the thread's dynamic string. The * current length may be bigger if previous operations in this thread have * caused it to increase. * * \return This function will return the thread locally stored dynamic string * associated with the thread storage management variable passed as the * first argument. * The result will be NULL in the case of a memory allocation error. * * Example usage: * \code * AST_THREADSTORAGE(my_str, my_str_init); * #define MY_STR_INIT_SIZE 128 * ... * void my_func(const char *fmt, ...) * { * struct ast_str *buf; * * if (!(buf = ast_str_thread_get(&my_str, MY_STR_INIT_SIZE))) * return; * ... * } * \endcode */#if !defined(DEBUG_THREADLOCALS)AST_INLINE_API(struct ast_str *ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len),{ struct ast_str *buf; buf = (struct ast_str *)ast_threadstorage_get(ts, sizeof(*buf) + init_len); if (buf == NULL) return NULL; if (!buf->len) { buf->len = init_len; buf->used = 0; buf->ts = ts; } return buf;})#else /* defined(DEBUG_THREADLOCALS) */AST_INLINE_API(struct ast_str *__ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len, const char *file, const char *function, unsigned int line),{ struct ast_str *buf; buf = (struct ast_str *)__ast_threadstorage_get(ts, sizeof(*buf) + init_len, file, function, line); if (buf == NULL) return NULL; if (!buf->len) { buf->len = init_len; buf->used = 0; buf->ts = ts; } return buf;})#define ast_str_thread_get(ts, init_len) __ast_str_thread_get(ts, init_len, __FILE__, __PRETTY_FUNCTION__, __LINE__)#endif /* defined(DEBUG_THREADLOCALS) *//*! * \brief Error codes from __ast_str_helper() * The undelying processing to manipulate dynamic string is done * by __ast_str_helper(), which can return a success, a * permanent failure (e.g. no memory), or a temporary one (when * the string needs to be reallocated, and we must run va_start() * again; XXX this convoluted interface is only here because * FreeBSD 4 lacks va_copy, but this will be fixed and the * interface simplified). */enum { /*! An error has occured and the contents of the dynamic string * are undefined */ AST_DYNSTR_BUILD_FAILED = -1, /*! The buffer size for the dynamic string had to be increased, and * __ast_str_helper() needs to be called again after * a va_end() and va_start(). */ AST_DYNSTR_BUILD_RETRY = -2};/*! * \brief Set a dynamic string from a va_list * * \arg buf This is the address of a pointer to a struct ast_str. * If it is retrieved using ast_str_thread_get, the struct ast_threadstorage pointer will need to * be updated in the case that the buffer has to be reallocated to * accommodate a longer string than what it currently has space for. * \arg max_len This is the maximum length to allow the string buffer to grow * to. If this is set to 0, then there is no maximum length. * \arg fmt This is the format string (printf style) * \arg ap This is the va_list * * \return The return value of this function is the same as that of the printf * family of functions. * * Example usage (the first part is only for thread-local storage) * \code * AST_THREADSTORAGE(my_str, my_str_init); * #define MY_STR_INIT_SIZE 128 * ... * void my_func(const char *fmt, ...) * { * struct ast_str *buf; * va_list ap; * * if (!(buf = ast_str_thread_get(&my_str, MY_STR_INIT_SIZE))) * return; * ... * va_start(fmt, ap); * ast_str_set_va(&buf, 0, fmt, ap); * va_end(ap); * * printf("This is the string we just built: %s\n", buf->str); * ... * } * \endcode * * \note: the following two functions must be implemented as macros * because we must do va_end()/va_start() on the original arguments. */#define ast_str_set_va(buf, max_len, fmt, ap) \ ({ \ int __res; \ while ((__res = __ast_str_helper(buf, max_len, \ 0, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) { \ va_end(ap); \ va_start(ap, fmt); \ } \ (__res); \ })/*! * \brief Append to a dynamic string using a va_list * * Same as ast_str_set_va(), but append to the current content. */#define ast_str_append_va(buf, max_len, fmt, ap) \ ({ \ int __res; \ while ((__res = __ast_str_helper(buf, max_len, \ 1, fmt, ap)) == AST_DYNSTR_BUILD_RETRY) { \ va_end(ap); \ va_start(ap, fmt); \ } \ (__res); \ })/*! * \brief Core functionality of ast_str_(set|append)_va * * The arguments to this function are the same as those described for * ast_str_set_va except for an addition argument, append. * If append is non-zero, this will append to the current string instead of * writing over it. * * In the case that this function is called and the buffer was not large enough * to hold the result, the partial write will be truncated, and the result * AST_DYNSTR_BUILD_RETRY will be returned to indicate that the buffer size * was increased, and the function should be called a second time. * * A return of AST_DYNSTR_BUILD_FAILED indicates a memory allocation error. * * A return value greater than or equal to zero indicates the number of * characters that have been written, not including the terminating '\0'. * In the append case, this only includes the number of characters appended. * * \note This function should never need to be called directly. It should * through calling one of the other functions or macros defined in this * file. */int __attribute__((format(printf, 4, 0))) __ast_str_helper(struct ast_str **buf, size_t max_len, int append, const char *fmt, va_list ap);/*! * \brief Set a dynamic string using variable arguments * * \arg buf This is the address of a pointer to a struct ast_str which should * have been retrieved using ast_str_thread_get. It will need to * be updated in the case that the buffer has to be reallocated to * accomodate a longer string than what it currently has space for. * \arg max_len This is the maximum length to allow the string buffer to grow * to. If this is set to 0, then there is no maximum length. * If set to -1, we are bound to the current maximum length. * \arg fmt This is the format string (printf style) * * \return The return value of this function is the same as that of the printf * family of functions. * * All the rest is the same as ast_str_set_va() */AST_INLINE_API(int __attribute__((format(printf, 3, 4))) ast_str_set( struct ast_str **buf, size_t max_len, const char *fmt, ...),{ int res; va_list ap; va_start(ap, fmt); res = ast_str_set_va(buf, max_len, fmt, ap); va_end(ap); return res;})/*! * \brief Append to a thread local dynamic string * * The arguments, return values, and usage of this function are the same as * ast_str_set(), but the new data is appended to the current value. */AST_INLINE_API(int __attribute__((format(printf, 3, 4))) ast_str_append( struct ast_str **buf, size_t max_len, const char *fmt, ...),{ int res; va_list ap; va_start(ap, fmt); res = ast_str_append_va(buf, max_len, fmt, ap); va_end(ap); return res;})/*! * \brief Compute a hash value on a string * * This famous hash algorithm was written by Dan Bernstein and is * commonly used. * * http://www.cse.yorku.ca/~oz/hash.html */static force_inline int ast_str_hash(const char *str){ int hash = 5381; while (*str) hash = hash * 33 ^ *str++; return abs(hash);}/*! * \brief Compute a hash value on a case-insensitive string * * Uses the same hash algorithm as ast_str_hash, but converts * all characters to lowercase prior to computing a hash. This * allows for easy case-insensitive lookups in a hash table. */static force_inline int ast_str_case_hash(const char *str){ int hash = 5381; while (*str) { hash = hash * 33 ^ tolower(*str++); } return abs(hash);}#endif /* _ASTERISK_STRINGS_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -