From c8223fc9578754dfaef1b337e5f0dfff546461b4 Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Sat, 13 Dec 2008 08:36:35 +0000 Subject: 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 --- main/Makefile | 3 +- main/app.c | 4 + main/asterisk.c | 10 +-- main/cdr.c | 5 +- main/cli.c | 17 +++-- main/config.c | 66 +++++++++-------- main/http.c | 6 +- main/logger.c | 8 +- main/manager.c | 26 ++++--- main/pbx.c | 222 +++++++++++++++++++++++++------------------------------ main/strings.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ main/tcptls.c | 2 +- main/translate.c | 2 +- main/utils.c | 60 --------------- main/xmldoc.c | 41 +++++----- 15 files changed, 420 insertions(+), 271 deletions(-) create mode 100644 main/strings.c (limited to 'main') diff --git a/main/Makefile b/main/Makefile index 56b964d16..54882f245 100644 --- a/main/Makefile +++ b/main/Makefile @@ -28,7 +28,8 @@ OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \ cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \ strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \ astobj2.o hashtab.o global_datastores.o version.o \ - features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o + features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \ + strings.o # we need to link in the objects statically, not as a library, because # otherwise modules will not have them available if none of the static diff --git a/main/app.c b/main/app.c index aecbffaf2..d3d3b3784 100644 --- a/main/app.c +++ b/main/app.c @@ -44,6 +44,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/lock.h" #include "asterisk/indications.h" #include "asterisk/linkedlists.h" +#include "asterisk/threadstorage.h" + +AST_THREADSTORAGE_PUBLIC(global_app_buf); + #define MAX_OTHER_FORMATS 10 diff --git a/main/asterisk.c b/main/asterisk.c index c002a4542..8fe421dde 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -2034,7 +2034,7 @@ static char *cli_prompt(EditLine *editline) if (prompt == NULL) { prompt = ast_str_create(100); } else if (!cli_prompt_changes) { - return prompt->str; + return ast_str_buffer(prompt); } else { ast_str_reset(prompt); } @@ -2132,11 +2132,7 @@ static char *cli_prompt(EditLine *editline) } t++; } else { - if (prompt->used + 5 > prompt->len) { - ast_str_make_space(&prompt, prompt->len + 5); - } - prompt->str[prompt->used++] = *t++; - prompt->str[prompt->used] = '\0'; + ast_str_append(&prompt, 0, "%c", *t); } } if (color_used) { @@ -2149,7 +2145,7 @@ static char *cli_prompt(EditLine *editline) ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT); } - return(prompt->str); + return ast_str_buffer(prompt); } static char **ast_el_strtoarr(char *buf) diff --git a/main/cdr.c b/main/cdr.c index f48ddf38d..991b01a25 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -367,8 +367,7 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char char workspace[256]; int total = 0, x = 0, i; - (*buf)->used = 0; - (*buf)->str[0] = '\0'; + ast_str_reset(*buf); for (; cdr; cdr = recur ? cdr->next : NULL) { if (++x > 1) @@ -776,7 +775,7 @@ void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chann) } } -void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data) +void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data) { for (; cdr; cdr = cdr->next) { diff --git a/main/cli.c b/main/cli.c index 063eeaae2..57f936b09 100644 --- a/main/cli.c +++ b/main/cli.c @@ -110,8 +110,9 @@ void ast_cli(int fd, const char *fmt, ...) res = ast_str_set_va(&buf, 0, fmt, ap); va_end(ap); - if (res != AST_DYNSTR_BUILD_FAILED) - ast_carefulwrite(fd, buf->str, strlen(buf->str), 100); + if (res != AST_DYNSTR_BUILD_FAILED) { + ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100); + } } unsigned int ast_debug_get_by_file(const char *file) @@ -637,9 +638,9 @@ static void print_uptimestr(int fd, struct timeval timeval, const char *prefix, ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec)); } x = timeval.tv_sec; - if (x > 0 || out->used == 0) /* if there is nothing, print 0 seconds */ + if (x > 0 || ast_str_strlen(out) == 0) /* if there is nothing, print 0 seconds */ ast_str_append(&out, 0, "%d second%s ", x, ESS(x)); - ast_cli(fd, "%s: %s\n", prefix, out->str); + ast_cli(fd, "%s: %s\n", prefix, ast_str_buffer(out)); } static struct ast_cli_entry *cli_next(struct ast_cli_entry *e) @@ -1258,7 +1259,7 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar { struct ast_channel *c=NULL; struct timeval now; - struct ast_str *out = ast_str_alloca(2048); + struct ast_str *out = ast_str_thread_get(&global_app_buf, 16); char cdrtime[256]; char nf[256], wf[256], rf[256]; long elapsed_seconds=0; @@ -1347,14 +1348,14 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); if (pbx_builtin_serialize_variables(c, &out)) - ast_cli(a->fd," Variables:\n%s\n", out->str); + ast_cli(a->fd," Variables:\n%s\n", ast_str_buffer(out)); if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1)) - ast_cli(a->fd," CDR Variables:\n%s\n", out->str); + ast_cli(a->fd," CDR Variables:\n%s\n", ast_str_buffer(out)); #ifdef CHANNEL_TRACE trace_enabled = ast_channel_trace_is_enabled(c); ast_cli(a->fd, " Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled"); if (trace_enabled && ast_channel_trace_serialize(c, &out)) - ast_cli(a->fd, " Trace:\n%s\n", out->str); + ast_cli(a->fd, " Trace:\n%s\n", ast_str_buffer(out)); #endif ast_channel_unlock(c); return CLI_SUCCESS; diff --git a/main/config.c b/main/config.c index 5fad1c51b..33a8ecb7b 100644 --- a/main/config.c +++ b/main/config.c @@ -106,19 +106,23 @@ static void CB_ADD_LEN(struct ast_str **cb, const char *str, int len) static void CB_RESET(struct ast_str *cb, struct ast_str *llb) { - if (cb) - cb->used = 0; - if (llb) - llb->used = 0; + if (cb) { + ast_str_reset(cb); + } + if (llb) { + ast_str_reset(llb); + } } -static struct ast_comment *ALLOC_COMMENT(const struct ast_str *buffer) +static struct ast_comment *ALLOC_COMMENT(struct ast_str *buffer) { struct ast_comment *x = NULL; - if (buffer && buffer->used) - x = ast_calloc(1, sizeof(*x) + buffer->used + 1); - if (x) - strcpy(x->cmt, buffer->str); + if (!buffer || !ast_str_strlen(buffer)) { + return NULL; + } + if ((x = ast_calloc(1, sizeof(*x) + ast_str_strlen(buffer) + 1))) { + strcpy(x->cmt, ast_str_buffer(buffer)); /* SAFE */ + } return x; } @@ -132,20 +136,21 @@ struct inclfile { static int hash_string(const void *obj, const int flags) { - char *str = ((struct inclfile*)obj)->fname; + char *str = ((struct inclfile *) obj)->fname; int total; - for (total=0; *str; str++) { + for (total = 0; *str; str++) { unsigned int tmp = total; total <<= 1; /* multiply by 2 */ total += tmp; /* multiply by 3 */ total <<= 2; /* multiply by 12 */ total += tmp; /* multiply by 13 */ - total += ((unsigned int)(*str)); + total += ((unsigned int) (*str)); } - if (total < 0) + if (total < 0) { total = -total; + } return total; } @@ -1125,7 +1130,8 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, ast_str_set(str, 0, "%s", replace->value); ast_str_append(str, 0, "%s", c); - ast_variable_update(*cat, replace->name, ast_strip((*str)->str), replace->value, object); + ast_str_trim_blanks(*str); + ast_variable_update(*cat, replace->name, ast_skip_blanks(ast_str_buffer(*str)), replace->value, object); } else if (c) { *c = 0; c++; @@ -1320,9 +1326,9 @@ static struct ast_config *config_text_file_load(const char *database, const char while (!feof(f)) { lineno++; if (fgets(buf, sizeof(buf), f)) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } new_buf = buf; @@ -1331,14 +1337,14 @@ static struct ast_config *config_text_file_load(const char *database, const char else process_buf = buf; - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer) && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) { /* blank line? really? Can we add it to an existing comment and maybe preserve inter- and post- comment spacing? */ CB_ADD(&comment_buffer, "\n"); /* add a newline to the comment buffer */ continue; /* go get a new line, then */ } while ((comment_p = strchr(new_buf, COMMENT_META))) { - if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) { + if ((comment_p > new_buf) && (*(comment_p - 1) == '\\')) { /* Escaped semicolons aren't comments. */ new_buf = comment_p + 1; } else if (comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) { @@ -1403,30 +1409,30 @@ static struct ast_config *config_text_file_load(const char *database, const char } /* end of file-- anything in a comment buffer? */ if (last_cat) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) { - if (lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + if (lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } last_cat->trailing = ALLOC_COMMENT(comment_buffer); } } else if (last_var) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) { - if (lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + if (lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } last_var->trailing = ALLOC_COMMENT(comment_buffer); } } else { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used) { - ast_debug(1, "Nothing to attach comments to, discarded: %s\n", comment_buffer->str); + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + ast_debug(1, "Nothing to attach comments to, discarded: %s\n", ast_str_buffer(comment_buffer)); } } if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) CB_RESET(comment_buffer, lline_buffer); - fclose(f); + fclose(f); } while (0); if (comment) { ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]); diff --git a/main/http.c b/main/http.c index 5c3aa7895..237ad6643 100644 --- a/main/http.c +++ b/main/http.c @@ -755,14 +755,14 @@ static void *httpd_helper_thread(void *data) * append a random variable to your GET request. Ex: 'something.html?r=109987734' */ if (!contentlength) { /* opaque body ? just dump it hoping it is properly formatted */ - fprintf(ser->f, "%s", out->str); + fprintf(ser->f, "%s", ast_str_buffer(out)); } else { - char *tmp = strstr(out->str, "\r\n\r\n"); + char *tmp = strstr(ast_str_buffer(out), "\r\n\r\n"); if (tmp) { fprintf(ser->f, "Content-length: %d\r\n", contentlength); /* first write the header, then the body */ - if (fwrite(out->str, 1, (tmp + 4 - out->str), ser->f) != tmp + 4 - out->str) { + if (fwrite(ast_str_buffer(out), 1, (tmp + 4 - ast_str_buffer(out)), ser->f) != tmp + 4 - ast_str_buffer(out)) { ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); } if (fwrite(tmp + 4, 1, contentlength, ser->f) != contentlength ) { diff --git a/main/logger.c b/main/logger.c index b42a21b19..8a577ed38 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1106,8 +1106,8 @@ void ast_log(int level, const char *file, int line, const char *function, const result = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */ va_end(ap); if (result != AST_DYNSTR_BUILD_FAILED) { - term_filter_escapes(buf->str); - fputs(buf->str, stdout); + term_filter_escapes(ast_str_buffer(buf)); + fputs(ast_str_buffer(buf), stdout); } } return; @@ -1140,7 +1140,7 @@ void ast_log(int level, const char *file, int line, const char *function, const return; /* Copy string over */ - strcpy(logmsg->str, buf->str); + strcpy(logmsg->str, ast_str_buffer(buf)); /* Set type to be normal */ logmsg->type = LOGMSG_NORMAL; @@ -1269,7 +1269,7 @@ void __ast_verbose_ap(const char *file, int line, const char *func, const char * if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1))) return; - strcpy(logmsg->str, buf->str); + strcpy(logmsg->str, ast_str_buffer(buf)); ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->str + 1); diff --git a/main/manager.c b/main/manager.c index 47a7f42b9..f3cda9e82 100644 --- a/main/manager.c +++ b/main/manager.c @@ -347,7 +347,7 @@ static char *authority_to_str(int authority, struct ast_str **res) int i; char *sep = ""; - (*res)->used = 0; + ast_str_reset(*res); for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { if (authority & perms[i].num) { ast_str_append(res, 0, "%s%s", sep, perms[i].label); @@ -355,10 +355,10 @@ static char *authority_to_str(int authority, struct ast_str **res) } } - if ((*res)->used == 0) /* replace empty string with something sensible */ + if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ ast_str_append(res, 0, ""); - return (*res)->str; + return ast_str_buffer(*res); } /*! Tells you if smallstr exists inside bigstr @@ -950,10 +950,11 @@ void astman_append(struct mansession *s, const char *fmt, ...) ast_str_set_va(&buf, 0, fmt, ap); va_end(ap); - if (s->f != NULL) - send_string(s, buf->str); - else + if (s->f != NULL) { + send_string(s, ast_str_buffer(buf)); + } else { ast_verbose("fd == -1 in astman_append, should not happen\n"); + } } /*! \note NOTE: XXX this comment is unclear and possibly wrong. @@ -1525,11 +1526,12 @@ static int action_createconfig(struct mansession *s, const struct message *m) ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); ast_str_append(&filepath, 0, "%s", fn); - if ((fd = open(filepath->str, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { + if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { close(fd); astman_send_ack(s, m, "New configuration file created successfully"); - } else + } else { astman_send_error(s, m, strerror(errno)); + } return 0; } @@ -1939,7 +1941,7 @@ static int action_status(struct mansession *s, const struct message *m) c->accountcode, c->_state, ast_state2str(c->_state), c->context, - c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, str->str, idText); + c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); } else { astman_append(s, "Event: Status\r\n" @@ -1958,7 +1960,7 @@ static int action_status(struct mansession *s, const struct message *m) S_OR(c->cid.cid_num, ""), S_OR(c->cid.cid_name, ""), c->accountcode, - ast_state2str(c->_state), bridge, c->uniqueid, str->str, idText); + ast_state2str(c->_state), bridge, c->uniqueid, ast_str_buffer(str), idText); } ast_channel_unlock(c); if (!all) @@ -3268,7 +3270,7 @@ int __manager_event(int category, const char *event, ast_str_append(&buf, 0, "\r\n"); - append_event(buf->str, category); + append_event(ast_str_buffer(buf), category); /* Wake up any sleeping sessions */ AST_LIST_LOCK(&sessions); @@ -3289,7 +3291,7 @@ int __manager_event(int category, const char *event, AST_RWLIST_RDLOCK(&manager_hooks); AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { - hook->helper(category, event, buf->str); + hook->helper(category, event, ast_str_buffer(buf)); } AST_RWLIST_UNLOCK(&manager_hooks); diff --git a/main/pbx.c b/main/pbx.c index 37ab4db7e..8fb1393ea 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -1504,7 +1504,7 @@ void log_match_char_tree(struct match_char *node, char *prefix) ast_str_set(&my_prefix, 0, "%s+ ", prefix); if (node->next_char) - log_match_char_tree(node->next_char, my_prefix->str); + log_match_char_tree(node->next_char, ast_str_buffer(my_prefix)); if (node->alt_char) log_match_char_tree(node->alt_char, prefix); @@ -1533,7 +1533,7 @@ static void cli_match_char_tree(struct match_char *node, char *prefix, int fd) ast_str_set(&my_prefix, 0, "%s+ ", prefix); if (node->next_char) - cli_match_char_tree(node->next_char, my_prefix->str, fd); + cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); if (node->alt_char) cli_match_char_tree(node->alt_char, prefix, fd); @@ -2525,8 +2525,8 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, break; } else if (eval) { /* Substitute variables now */ - pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); - datap = tmpdata->str; + pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); + datap = ast_str_buffer(tmpdata); } else { datap = osw; } @@ -2695,7 +2695,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, ast_log(LOG_WARNING, "Can't evaluate switch?!"); continue; } - pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); + pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); } /* equivalent of extension_match_core() at the switch level */ @@ -2705,7 +2705,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, aswf = asw->matchmore; else /* action == E_MATCH */ aswf = asw->exists; - datap = sw->eval ? tmpdata->str : sw->data; + datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; if (!aswf) res = 0; else { @@ -3351,11 +3351,11 @@ int ast_func_write(struct ast_channel *chan, const char *function, const char *v return -1; } -static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) { /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ char *cp4; - const char *tmp, *whereweare; + const char *tmp, *whereweare, *orig_cp2 = cp2; int length, offset, offset2, isfunction; char *workspace = NULL; char *ltmp = NULL, *var = NULL; @@ -3435,10 +3435,11 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v /* Substitute if necessary */ if (needsub) { + size_t used; if (!ltmp) ltmp = alloca(VAR_BUF_SIZE); - pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); + pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); vars = ltmp; } else { vars = var; @@ -3522,10 +3523,11 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v /* Substitute if necessary */ if (needsub) { + size_t used; if (!ltmp) ltmp = alloca(VAR_BUF_SIZE); - pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); + pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); vars = ltmp; } else { vars = var; @@ -3541,16 +3543,19 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v } } } + *used = cp2 - orig_cp2; } void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count) { - pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); + size_t used; + pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); } void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count) { - pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); + size_t used; + pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); } static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) @@ -3725,7 +3730,7 @@ static int ast_extension_state2(struct ast_exten *e) ast_str_set(&hint, 0, "%s", ast_get_extension_app(e)); - rest = hint->str; /* One or more devices separated with a & character */ + rest = ast_str_buffer(hint); /* One or more devices separated with a & character */ while ( (cur = strsep(&rest, "&")) ) ast_devstate_aggregate_add(&agg, ast_device_state(cur)); @@ -6089,8 +6094,8 @@ static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cl } pbx_builtin_serialize_variables(chan, &vars); - if (vars->str) { - ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str); + if (ast_str_strlen(vars)) { + ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); } ast_channel_unlock(chan); return CLI_SUCCESS; @@ -6637,15 +6642,20 @@ static int lookup_name(const char *s, char *const names[], int max) { int i; - if (names) { + if (names && *s > '9') { for (i = 0; names[i]; i++) { - if (!strcasecmp(s, names[i])) - return i+1; + if (!strcasecmp(s, names[i])) { + return i; + } } - } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { - return i; } - return 0; /* error return */ + + /* Allow months and weekdays to be specified as numbers, as well */ + if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { + /* What the array offset would have been: "1" would be at offset 0 */ + return i - 1; + } + return -1; /* error return */ } /*! \brief helper function to return a range up to max (7, 12, 31 respectively). @@ -6653,131 +6663,104 @@ static int lookup_name(const char *s, char *const names[], int max) */ static unsigned get_range(char *src, int max, char *const names[], const char *msg) { - int s, e; /* start and ending position */ + int start, end; /* start and ending position */ unsigned int mask = 0; + char *part; /* Check for whole range */ if (ast_strlen_zero(src) || !strcmp(src, "*")) { - s = 0; - e = max - 1; - } else { + return (1 << max) - 1; + } + + while ((part = strsep(&src, "&"))) { /* Get start and ending position */ - char *c = strchr(src, '-'); - if (c) - *c++ = '\0'; + char *endpart = strchr(part, '-'); + if (endpart) { + *endpart++ = '\0'; + } /* Find the start */ - s = lookup_name(src, names, max); - if (!s) { - ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); - return 0; + if ((start = lookup_name(part, names, max)) < 0) { + ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); + continue; } - s--; - if (c) { /* find end of range */ - e = lookup_name(c, names, max); - if (!e) { - ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); - return 0; + if (endpart) { /* find end of range */ + if ((end = lookup_name(endpart, names, max)) < 0) { + ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); + continue; } - e--; - } else - e = s; - } - /* Fill the mask. Remember that ranges are cyclic */ - mask = 1 << e; /* initialize with last element */ - while (s != e) { - if (s >= max) { - s = 0; - mask |= (1 << s); } else { - mask |= (1 << s); - s++; + end = start; + } + /* Fill the mask. Remember that ranges are cyclic */ + mask |= (1 << end); /* initialize with last element */ + while (start != end) { + if (start >= max) { + start = 0; + } + mask |= (1 << start); + start++; } } return mask; } -/*! \brief store a bitmask of valid times, one bit each 2 minute */ +/*! \brief store a bitmask of valid times, one bit each 1 minute */ static void get_timerange(struct ast_timing *i, char *times) { - char *e; + char *endpart, *part; int x; - int s1, s2; - int e1, e2; - /* int cth, ctm; */ + int st_h, st_m; + int endh, endm; + int minute_start, minute_end; /* start disabling all times, fill the fields with 0's, as they may contain garbage */ memset(i->minmask, 0, sizeof(i->minmask)); - /* 2-minutes per bit, since the mask has only 32 bits :( */ + /* 1-minute per bit */ /* Star is all times */ if (ast_strlen_zero(times) || !strcmp(times, "*")) { - for (x = 0; x < 24; x++) + /* 48, because each hour takes 2 integers; 30 bits each */ + for (x = 0; x < 48; x++) { i->minmask[x] = 0x3fffffff; /* 30 bits */ + } return; } /* Otherwise expect a range */ - e = strchr(times, '-'); - if (!e) { - ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); - return; - } - *e++ = '\0'; - /* XXX why skip non digits ? */ - while (*e && !isdigit(*e)) - e++; - if (!*e) { - ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); - return; - } - if (sscanf(times, "%d:%d", &s1, &s2) != 2) { - ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); - return; - } - if (sscanf(e, "%d:%d", &e1, &e2) != 2) { - ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); - return; - } - /* XXX this needs to be optimized */ -#if 1 - s1 = s1 * 30 + s2/2; - if ((s1 < 0) || (s1 >= 24*30)) { - ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); - return; - } - e1 = e1 * 30 + e2/2; - if ((e1 < 0) || (e1 >= 24*30)) { - ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); - return; - } - /* Go through the time and enable each appropriate bit */ - for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { - i->minmask[x/30] |= (1 << (x % 30)); - } - /* Do the last one */ - i->minmask[x/30] |= (1 << (x % 30)); -#else - for (cth = 0; cth < 24; cth++) { - /* Initialize masks to blank */ - i->minmask[cth] = 0; - for (ctm = 0; ctm < 30; ctm++) { - if ( - /* First hour with more than one hour */ - (((cth == s1) && (ctm >= s2)) && - ((cth < e1))) - /* Only one hour */ - || (((cth == s1) && (ctm >= s2)) && - ((cth == e1) && (ctm <= e2))) - /* In between first and last hours (more than 2 hours) */ - || ((cth > s1) && - (cth < e1)) - /* Last hour with more than one hour */ - || ((cth > s1) && - ((cth == e1) && (ctm <= e2))) - ) - i->minmask[cth] |= (1 << (ctm / 2)); + while ((part = strsep(×, "&"))) { + if (!(endpart = strchr(part, '-'))) { + if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { + ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); + continue; + } + i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); + continue; + } + *endpart++ = '\0'; + /* why skip non digits? Mostly to skip spaces */ + while (*endpart && !isdigit(*endpart)) { + endpart++; + } + if (!*endpart) { + ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); + continue; + } + if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { + ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); + continue; + } + if (sscanf(endpart, "%d:%d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { + ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); + continue; } + minute_start = st_h * 60 + st_m; + minute_end = endh * 60 + endm; + /* Go through the time and enable each appropriate bit */ + for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { + i->minmask[x / 30] |= (1 << (x % 30)); + } + /* Do the last one */ + i->minmask[x / 30] |= (1 << (x % 30)); } -#endif /* All done */ return; } @@ -6865,7 +6848,7 @@ int ast_check_timing(const struct ast_timing *i) /* Now the tough part, we calculate if it fits in the right time based on min/hour */ - if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) + if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) return 0; /* If we got this far, then we're good */ @@ -8662,8 +8645,7 @@ int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **b if (!chan) return 0; - (*buf)->used = 0; - (*buf)->str[0] = '\0'; + ast_str_reset(*buf); ast_channel_lock(chan); diff --git a/main/strings.c b/main/strings.c new file mode 100644 index 000000000..1fd1cac54 --- /dev/null +++ b/main/strings.c @@ -0,0 +1,219 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2008, Digium, Inc. + * + * Tilghman Lesher + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of +* the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief String manipulation API + * + * \author Tilghman Lesher + */ + +/*** MAKEOPTS + + + yes + + + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/strings.h" +#include "asterisk/pbx.h" + +/*! + * core handler for dynamic strings. + * This is not meant to be called directly, but rather through the + * various wrapper macros + * ast_str_set(...) + * ast_str_append(...) + * ast_str_set_va(...) + * ast_str_append_va(...) + */ + +int __ast_str_helper(struct ast_str **buf, size_t max_len, + int append, const char *fmt, va_list ap) +{ + int res, need; +#ifdef DEBUG_OPAQUE + int offset = (append && (*buf)->len2) ? (*buf)->used2 : 0; +#else + int offset = (append && (*buf)->len) ? (*buf)->used : 0; +#endif + va_list aq; + + do { + if (max_len < 0) { +#ifdef DEBUG_OPAQUE + max_len = (*buf)->len2; /* don't exceed the allocated space */ +#else + max_len = (*buf)->len; /* don't exceed the allocated space */ +#endif + } + /* + * Ask vsnprintf how much space we need. Remember that vsnprintf + * does not count the final '\0' so we must add 1. + */ + va_copy(aq, ap); +#ifdef DEBUG_OPAQUE + res = vsnprintf((*buf)->str2 + offset, (*buf)->len2 - offset, fmt, aq); +#else + res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq); +#endif + + need = res + offset + 1; + /* + * If there is not enough space and we are below the max length, + * reallocate the buffer and return a message telling to retry. + */ +#ifdef DEBUG_OPAQUE + if (need > (*buf)->len2 && (max_len == 0 || (*buf)->len2 < max_len) ) { +#else + if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { +#endif + if (max_len && max_len < need) { /* truncate as needed */ + need = max_len; + } else if (max_len == 0) { /* if unbounded, give more room for next time */ + need += 16 + need / 4; + } + if (0) { /* debugging */ +#ifdef DEBUG_OPAQUE + ast_verbose("extend from %d to %d\n", (int)(*buf)->len2, need); +#else + ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need); +#endif + } + if (ast_str_make_space(buf, need)) { +#ifdef DEBUG_OPAQUE + ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len2, need); +#else + ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need); +#endif + return AST_DYNSTR_BUILD_FAILED; + } +#ifdef DEBUG_OPAQUE + (*buf)->str2[offset] = '\0'; /* Truncate the partial write. */ +#else + (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ +#endif + + /* Restart va_copy before calling vsnprintf() again. */ + va_end(aq); + continue; + } + break; + } while (1); + /* update space used, keep in mind the truncation */ +#ifdef DEBUG_OPAQUE + (*buf)->used2 = (res + offset > (*buf)->len2) ? (*buf)->len2 : res + offset; +#else + (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; +#endif + + return res; +} + +void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *template) +{ + int first = 1; +#ifdef DEBUG_OPAQUE + do { + ast_str_make_space(buf, maxlen ? maxlen : + (first ? strlen(template) * 2 : (*buf)->len2 * 2)); + pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str2, (*buf)->len2 - 1, &((*buf)->used2)); + first = 0; + } while (maxlen == 0 && (*buf)->len2 - 5 < (*buf)->used2); +#else + do { + ast_str_make_space(buf, maxlen ? maxlen : + (first ? strlen(template) * 2 : (*buf)->len * 2)); + pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str, (*buf)->len - 1, &((*buf)->used)); + first = 0; + } while (maxlen == 0 && (*buf)->len - 5 < (*buf)->used); +#endif +} + +char *__ast_str_helper2(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc, int append, int escapecommas) +{ + int dynamic = 0; +#ifdef DEBUG_OPAQUE + char *ptr = append ? &((*buf)->str2[(*buf)->used2]) : (*buf)->str2; +#else + char *ptr = append ? &((*buf)->str[(*buf)->used]) : (*buf)->str; +#endif + + if (!maxlen) { + dynamic = 1; +#ifdef DEBUG_OPAQUE + maxlen = (*buf)->len2; +#else + maxlen = (*buf)->len; +#endif + } + + while (*src && maxsrc && maxlen && (!escapecommas || (maxlen - 1))) { + if (escapecommas && (*src == '\\' || *src == ',')) { + *ptr++ = '\\'; + maxlen--; +#ifdef DEBUG_OPAQUE + (*buf)->used2++; +#else + (*buf)->used++; +#endif + } + *ptr++ = *src++; + maxsrc--; + maxlen--; +#ifdef DEBUG_OPAQUE + (*buf)->used2++; +#else + (*buf)->used++; +#endif + if (dynamic && (!maxlen || (escapecommas && !(maxlen - 1)))) { +#ifdef DEBUG_OPAQUE + size_t old = (*buf)->len2; + if (ast_str_make_space(buf, (*buf)->len2 * 2)) { + /* If the buffer can't be extended, end it. */ + break; + } +#else + size_t old = (*buf)->len; + if (ast_str_make_space(buf, (*buf)->len * 2)) { + /* If the buffer can't be extended, end it. */ + break; + } +#endif + /* What we extended the buffer by */ + maxlen = old; + } + } + if (__builtin_expect(!(maxsrc && maxlen), 0)) { + ptr--; + } + *ptr = '\0'; +#ifdef DEBUG_OPAQUE + (*buf)->used2--; + return (*buf)->str2; +#else + (*buf)->used--; + return (*buf)->str; +#endif +} + diff --git a/main/tcptls.c b/main/tcptls.c index b93c53bae..b1c615aea 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -97,7 +97,7 @@ HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *tcptls_session return read(tcptls_session->fd, buf, count); } -HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count) +HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count) { if (tcptls_session->fd == -1) { ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); diff --git a/main/translate.c b/main/translate.c index 35c1968df..5d4fd0ace 100644 --- a/main/translate.c +++ b/main/translate.c @@ -598,7 +598,7 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, } } ast_str_append(&out, -1, "\n"); - ast_cli(a->fd, "%s", out->str); + ast_cli(a->fd, "%s", ast_str_buffer(out)); } AST_RWLIST_UNLOCK(&translators); return CLI_SUCCESS; diff --git a/main/utils.c b/main/utils.c index 71a4dcc00..6651f9281 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1587,66 +1587,6 @@ int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed) return -1; } -/*! - * core handler for dynamic strings. - * This is not meant to be called directly, but rather through the - * various wrapper macros - * ast_str_set(...) - * ast_str_append(...) - * ast_str_set_va(...) - * ast_str_append_va(...) - */ - -int __ast_str_helper(struct ast_str **buf, size_t max_len, - int append, const char *fmt, va_list ap) -{ - int res, need; - int offset = (append && (*buf)->len) ? (*buf)->used : 0; - va_list aq; - - do { - if (max_len < 0) { - max_len = (*buf)->len; /* don't exceed the allocated space */ - } - /* - * Ask vsnprintf how much space we need. Remember that vsnprintf - * does not count the final '\0' so we must add 1. - */ - va_copy(aq, ap); - res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq); - - need = res + offset + 1; - /* - * If there is not enough space and we are below the max length, - * reallocate the buffer and return a message telling to retry. - */ - if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { - if (max_len && max_len < need) { /* truncate as needed */ - need = max_len; - } else if (max_len == 0) { /* if unbounded, give more room for next time */ - need += 16 + need / 4; - } - if (0) { /* debugging */ - ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need); - } - if (ast_str_make_space(buf, need)) { - ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need); - return AST_DYNSTR_BUILD_FAILED; - } - (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ - - /* Restart va_copy before calling vsnprintf() again. */ - va_end(aq); - continue; - } - break; - } while (1); - /* update space used, keep in mind the truncation */ - (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; - - return res; -} - void ast_enable_packet_fragmentation(int sock) { #if defined(HAVE_IP_MTU_DISCOVER) diff --git a/main/xmldoc.c b/main/xmldoc.c index 3185a3a56..1cd3a0909 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -268,8 +268,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff) backspace = xmldoc_foundspace_backward(text, i, maxdiff); if (backspace) { needtobreak = 1; - tmp->used -= backspace; - tmp->str[tmp->used] = '\0'; + ast_str_truncate(tmp, -backspace); i -= backspace + 1; continue; } @@ -300,7 +299,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff) ast_str_append(&tmp, 0, "%c", text[i]); } - ret = ast_strdup(tmp->str); + ret = ast_strdup(ast_str_buffer(tmp)); ast_free(tmp); return ret; @@ -403,7 +402,7 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors) } /* Wrap the text, notice that string wrap will avoid cutting an ESC sequence. */ - wrapped = xmldoc_string_wrap(colorized->str, xmldoc_text_columns, xmldoc_max_diff); + wrapped = xmldoc_string_wrap(ast_str_buffer(colorized), xmldoc_text_columns, xmldoc_max_diff); ast_free(colorized); @@ -881,7 +880,7 @@ static char *xmldoc_parse_cmd_enumlist(struct ast_xml_node *fixnode) ast_str_append(¶mname, 0, "}"); - ret = ast_strdup(paramname->str); + ret = ast_strdup(ast_str_buffer(paramname)); ast_free(paramname); return ret; @@ -978,7 +977,7 @@ static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *nam } /* return a common string. */ - ret = ast_strdup(syntax->str); + ret = ast_strdup(ast_str_buffer(syntax)); ast_free(syntax); return ret; @@ -1084,9 +1083,9 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const if (tmpstr) { if (strcasecmp(ast_xml_node_get_name(tmp), "text")) { ast_str_append(buffer, 0, "<%s>%s", ast_xml_node_get_name(tmp), - tmpstr->str, ast_xml_node_get_name(tmp)); + ast_str_buffer(tmpstr), ast_xml_node_get_name(tmp)); } else { - ast_str_append(buffer, 0, "%s", tmpstr->str); + ast_str_append(buffer, 0, "%s", ast_str_buffer(tmpstr)); } ast_free(tmpstr); ret = 2; @@ -1245,8 +1244,8 @@ static int xmldoc_parse_variable(struct ast_xml_node *node, const char *tabs, st /* Cleanup text. */ xmldoc_string_cleanup(tmptext, &cleanstr, 1); ast_xml_free_text(tmptext); - if (cleanstr && cleanstr->used > 0) { - ast_str_append(buffer, 0, ":%s", cleanstr->str); + if (cleanstr && ast_str_strlen(cleanstr) > 0) { + ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr)); } ast_free(cleanstr); } @@ -1381,7 +1380,7 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name) ast_xml_free_text(content); } - output = ast_strdup(outputstr->str); + output = ast_strdup(ast_str_buffer(outputstr)); ast_free(outputstr); return output; @@ -1631,13 +1630,13 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name) xmldoc_parse_parameter(node, "", &ret); } - if (ret->used > 0) { + if (ast_str_strlen(ret) > 0) { /* remove last '\n' */ - if (ret->str[ret->used - 1] == '\n') { - ret->str[ret->used - 1] = '\0'; - ret->used--; + char *buf = ast_str_buffer(ret); + if (buf[ast_str_strlen(ret) - 1] == '\n') { + ast_str_truncate(ret, -1); } - retstr = ast_strdup(ret->str); + retstr = ast_strdup(ast_str_buffer(ret)); } ast_free(ret); @@ -1677,9 +1676,9 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o } /* remove last '\n' */ /* XXX Don't modify ast_str internals manually */ - if (ret->str[ret->used-1] == '\n') { - ret->str[ret->used-1] = '\0'; - ret->used--; + tmpstr = ast_str_buffer(ret); + if (tmpstr[ast_str_strlen(ret) - 1] == '\n') { + ast_str_truncate(ret, -1); } } return ret; @@ -1720,8 +1719,8 @@ static char *xmldoc_build_field(const char *type, const char *name, const char * } formatted = xmldoc_get_formatted(node, raw, raw); - if (formatted->used > 0) { - ret = ast_strdup(formatted->str); + if (ast_str_strlen(formatted) > 0) { + ret = ast_strdup(ast_str_buffer(formatted)); } ast_free(formatted); -- cgit v1.2.3