Merge ast_str_opaque branch (discontinue usage of ast_str internals)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@163991 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher
2008-12-13 08:36:35 +00:00
parent 3b96ae826e
commit c8223fc957
53 changed files with 1264 additions and 917 deletions

View File

@@ -23,14 +23,17 @@
#ifndef _ASTERISK_STRINGS_H
#define _ASTERISK_STRINGS_H
#define DEBUG_OPAQUE
#include <ctype.h>
#include "asterisk/inline_api.h"
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
/* You may see casts in this header that may seem useless but they ensure this file is C++ clean */
#define AS_OR(a,b) ast_str_strlen(a) ? ast_str_buffer(a) : (b)
#ifdef AST_DEVMODE
#define ast_strlen_zero(foo) _ast_strlen_zero(foo, __FILE__, __PRETTY_FUNCTION__, __LINE__)
static force_inline int _ast_strlen_zero(const char *s, const char *file, const char *function, int line)
@@ -202,7 +205,6 @@ void ast_copy_string(char *dst, const char *src, size_t size),
}
)
/*!
\brief Build a string in a buffer, designed to be called repeatedly
@@ -338,13 +340,23 @@ int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default
* struct ast_threadstorage pointer.
*/
struct ast_str {
#ifdef DEBUG_OPAQUE
size_t len2;
size_t used2;
struct ast_threadstorage *ts2;
#else
size_t len; /*!< The current maximum length of the string */
size_t used; /*!< Amount of space used */
struct ast_threadstorage *ts; /*!< What kind of storage is this ? */
#endif
#define DS_MALLOC ((struct ast_threadstorage *)1)
#define DS_ALLOCA ((struct ast_threadstorage *)2)
#define DS_STATIC ((struct ast_threadstorage *)3) /* not supported yet */
#ifdef DEBUG_OPAQUE
char str2[0];
#else
char str[0]; /*!< The string buffer */
#endif
};
/*!
@@ -366,10 +378,16 @@ struct ast_str * attribute_malloc ast_str_create(size_t init_len),
buf = (struct ast_str *)ast_calloc(1, sizeof(*buf) + init_len);
if (buf == NULL)
return NULL;
#ifdef DEBUG_OPAQUE
buf->len2 = init_len;
buf->used2 = 0;
buf->ts2 = DS_MALLOC;
#else
buf->len = init_len;
buf->used = 0;
buf->ts = DS_MALLOC;
#endif
return buf;
}
@@ -382,9 +400,15 @@ AST_INLINE_API(
void ast_str_reset(struct ast_str *buf),
{
if (buf) {
#ifdef DEBUG_OPAQUE
buf->used2 = 0;
if (buf->len2)
buf->str2[0] = '\0';
#else
buf->used = 0;
if (buf->len)
buf->str[0] = '\0';
#endif
}
}
)
@@ -398,12 +422,83 @@ void ast_str_trim_blanks(struct ast_str *buf),
if (!buf) {
return;
}
#ifdef DEBUG_OPAQUE
while (buf->used2 && buf->str2[buf->used2 - 1] < 33) {
buf->str2[--(buf->used2)] = '\0';
}
#else
while (buf->used && buf->str[buf->used - 1] < 33) {
buf->str[--(buf->used)] = '\0';
}
#endif
}
)
/*!\brief Returns the current length of the string stored within buf.
* \param A pointer to the ast_str string.
*/
AST_INLINE_API(
size_t ast_str_strlen(struct ast_str *buf),
{
#ifdef DEBUG_OPAQUE
return buf->used2;
#else
return buf->used;
#endif
}
)
/*!\brief Returns the current maximum length (without reallocation) of the current buffer.
* \param A pointer to the ast_str string.
*/
AST_INLINE_API(
size_t ast_str_size(struct ast_str *buf),
{
#ifdef DEBUG_OPAQUE
return buf->len2;
#else
return buf->len;
#endif
}
)
/*!\brief Returns the string buffer within the ast_str buf.
* \param A pointer to the ast_str string.
*/
AST_INLINE_API(
attribute_pure char *ast_str_buffer(struct ast_str *buf),
{
#ifdef DEBUG_OPAQUE
return buf->str2;
#else
return buf->str;
#endif
}
)
AST_INLINE_API(
char *ast_str_truncate(struct ast_str *buf, size_t len),
{
#ifdef DEBUG_OPAQUE
if (len < 0) {
buf->used2 += len;
} else {
buf->used2 = len;
}
buf->str2[buf->used2] = '\0';
return buf->str2;
#else
if (len < 0) {
buf->used += len;
} else {
buf->used = len;
}
buf->str[buf->used] = '\0';
return buf->str;
#endif
}
)
/*
* 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
@@ -427,6 +522,23 @@ int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file,
{
struct ast_str *old_buf = *buf;
#ifdef DEBUG_OPAQUE
if (new_len <= (*buf)->len2)
return 0; /* success */
if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC)
return -1; /* cannot extend */
*buf = (struct ast_str *)__ast_realloc(*buf, new_len + sizeof(struct ast_str), file, lineno, function);
if (*buf == NULL) {
*buf = old_buf;
return -1;
}
if ((*buf)->ts2 != DS_MALLOC) {
pthread_setspecific((*buf)->ts2->key, *buf);
_DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));)
}
(*buf)->len2 = new_len;
#else
if (new_len <= (*buf)->len)
return 0; /* success */
if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC)
@@ -442,6 +554,7 @@ int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file,
}
(*buf)->len = new_len;
#endif
return 0;
}
)
@@ -452,6 +565,23 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len),
{
struct ast_str *old_buf = *buf;
#ifdef DEBUG_OPAQUE
if (new_len <= (*buf)->len2)
return 0; /* success */
if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC)
return -1; /* cannot extend */
*buf = (struct ast_str *)ast_realloc(*buf, new_len + sizeof(struct ast_str));
if (*buf == NULL) {
*buf = old_buf;
return -1;
}
if ((*buf)->ts2 != DS_MALLOC) {
pthread_setspecific((*buf)->ts2->key, *buf);
_DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));)
}
(*buf)->len2 = new_len;
#else
if (new_len <= (*buf)->len)
return 0; /* success */
if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC)
@@ -467,11 +597,24 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len),
}
(*buf)->len = new_len;
#endif
return 0;
}
)
#endif
#ifdef DEBUG_OPAQUE
#define ast_str_alloca(init_len) \
({ \
struct ast_str *__ast_str_buf; \
__ast_str_buf = alloca(sizeof(*__ast_str_buf) + init_len); \
__ast_str_buf->len2 = init_len; \
__ast_str_buf->used2 = 0; \
__ast_str_buf->ts2 = DS_ALLOCA; \
__ast_str_buf->str2[0] = '\0'; \
(__ast_str_buf); \
})
#else
#define ast_str_alloca(init_len) \
({ \
struct ast_str *__ast_str_buf; \
@@ -482,6 +625,7 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len),
__ast_str_buf->str[0] = '\0'; \
(__ast_str_buf); \
})
#endif
/*!
* \brief Retrieve a thread locally stored dynamic string
@@ -524,12 +668,20 @@ struct ast_str *ast_str_thread_get(struct ast_threadstorage *ts,
buf = (struct ast_str *)ast_threadstorage_get(ts, sizeof(*buf) + init_len);
if (buf == NULL)
return NULL;
#ifdef DEBUG_OPAQUE
if (!buf->len2) {
buf->len2 = init_len;
buf->used2 = 0;
buf->ts2 = ts;
}
#else
if (!buf->len) {
buf->len = init_len;
buf->used = 0;
buf->ts = ts;
}
#endif
return buf;
}
@@ -544,12 +696,20 @@ struct ast_str *__ast_str_thread_get(struct ast_threadstorage *ts,
buf = (struct ast_str *)__ast_threadstorage_get(ts, sizeof(*buf) + init_len, file, function, line);
if (buf == NULL)
return NULL;
#ifdef DEBUG_OPAQUE
if (!buf->len2) {
buf->len2 = init_len;
buf->used2 = 0;
buf->ts2 = ts;
}
#else
if (!buf->len) {
buf->len = init_len;
buf->used = 0;
buf->ts = ts;
}
#endif
return buf;
}
@@ -599,6 +759,8 @@ enum {
*/
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);
char *__ast_str_helper2(struct ast_str **buf, size_t max_len,
const char *src, size_t maxsrc, int append, int escapecommas);
/*!
* \brief Set a dynamic string from a va_list
@@ -655,6 +817,78 @@ AST_INLINE_API(int __attribute__((format(printf, 3, 0))) ast_str_append_va(struc
}
)
/*!\brief Set a dynamic string to a non-NULL terminated substring. */
AST_INLINE_API(char *ast_str_set_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
{
return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 0);
}
)
/*!\brief Append a non-NULL terminated substring to the end of a dynamic string. */
AST_INLINE_API(char *ast_str_append_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
{
return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 0);
}
)
/*!\brief Set a dynamic string to a non-NULL terminated substring, with escaping of commas. */
AST_INLINE_API(char *ast_str_set_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
{
return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 1);
}
)
/*!\brief Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas. */
AST_INLINE_API(char *ast_str_append_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc),
{
return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 1);
}
)
/*!\brief Wrapper for SQLGetData to use with dynamic strings
* \param buf Address of the pointer to the ast_str structure.
* \param maxlen The maximum size of the resulting string, or 0 for no limit.
* \param StatementHandle The statement handle from which to retrieve data.
* \param ColumnNumber Column number (1-based offset) for which to retrieve data.
* \param TargetType The SQL constant indicating what kind of data is to be retrieved (usually SQL_CHAR)
* \param StrLen_or_Ind A pointer to a length indicator, specifying the total length of data.
*/
#ifdef USE_ODBC
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
AST_INLINE_API(SQLRETURN ast_str_SQLGetData(struct ast_str **buf, size_t maxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind),
{
SQLRETURN res;
if (maxlen == 0) {
#ifdef DEBUG_OPAQUE
if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
ast_str_make_space(buf, *StrLen_or_Ind + 1);
}
maxlen = (*buf)->len2;
} else if (maxlen > 0) {
ast_str_make_space(buf, maxlen);
}
res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, maxlen, StrLen_or_Ind);
(*buf)->used2 = *StrLen_or_Ind;
#else
if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
ast_str_make_space(buf, *StrLen_or_Ind + 1);
}
maxlen = (*buf)->len;
} else if (maxlen > 0) {
ast_str_make_space(buf, maxlen);
}
res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, maxlen, StrLen_or_Ind);
(*buf)->used = *StrLen_or_Ind;
#endif
return res;
}
)
#endif /* defined(USE_ODBC) */
/*!
* \brief Set a dynamic string using variable arguments
*