List improvements from kpfleming (bugs #3166,#3140)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4629 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2005-01-01 21:26:37 +00:00
parent b87a692804
commit 7abe9e6c16
6 changed files with 60 additions and 19 deletions

View File

@@ -191,7 +191,7 @@ static int del_identifier(int identifier,int identifier_type) {
AST_LIST_TRAVERSE(headp,i,entries) { AST_LIST_TRAVERSE(headp,i,entries) {
if ((i->identifier==identifier) && if ((i->identifier==identifier) &&
(i->identifier_type==identifier_type)) { (i->identifier_type==identifier_type)) {
AST_LIST_REMOVE(headp,i,ast_PGSQL_id,entries); AST_LIST_REMOVE(headp,i,entries);
free(i); free(i);
found=1; found=1;
break; break;

View File

@@ -673,7 +673,7 @@ void ast_channel_free(struct ast_channel *chan)
/* no need to lock the list, as the channel is already locked */ /* no need to lock the list, as the channel is already locked */
while (!AST_LIST_EMPTY(headp)) { /* List Deletion. */ while (!AST_LIST_EMPTY(headp)) { /* List Deletion. */
vardata = AST_LIST_REMOVE_HEAD(headp, ast_var_t, entries); vardata = AST_LIST_REMOVE_HEAD(headp, entries);
/* printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); */ /* printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); */
ast_var_delete(vardata); ast_var_delete(vardata);
} }

View File

@@ -147,6 +147,50 @@ struct { \
#define AST_LIST_TRAVERSE(head,var,field) \ #define AST_LIST_TRAVERSE(head,var,field) \
for((var) = (head)->first; (var); (var) = (var)->field.next) for((var) = (head)->first; (var); (var) = (var)->field.next)
/*!
\brief Loops safely over (traverses) the entries in a list.
\param head This is a pointer to the list head structure
\param var This is the name of the variable that will hold a pointer to the
current list entry on each iteration. It must be declared before calling
this macro.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
This macro is used to safely loop over (traverse) the entries in a list. It
uses a \a for loop, and supplies the enclosed code with a pointer to each list
entry as it loops. It is typically used as follows:
\code
static AST_LIST_HEAD(entry_list, list_entry) entries;
...
struct list_entry {
...
AST_LIST_ENTRY(list_entry) list;
}
...
struct list_entry *current;
...
AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list_entry, list) {
(do something with current here)
}
AST_LIST_TRAVERSE_SAFE_END
\endcode
It differs from AST_LIST_TRAVERSE in that the code inside the loop can modify
(or even free) the entry pointed to by the \a current pointer without affecting
the loop traversal.
*/
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \
typeof((head)->first) __list_next; \
for ((var) = (head)->first, __list_next = (var) ? (var)->field.next : NULL; \
(var); \
(var) = __list_next, __list_next = (var) ? (var)->field.next : NULL \
)
/*!
\brief Closes a safe loop traversal block.
*/
#define AST_LIST_TRAVERSE_SAFE_END }
/*! /*!
\brief Initializes a list head structure. \brief Initializes a list head structure.
\param head This is a pointer to the list head structure \param head This is a pointer to the list head structure
@@ -188,34 +232,32 @@ struct { \
\brief Inserts a list entry at the tail of a list. \brief Inserts a list entry at the tail of a list.
\param head This is a pointer to the list head structure \param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be inserted. \param elm This is a pointer to the entry to be inserted.
\param type This is the type of each list entry.
\param field This is the name of the field (declared using AST_LIST_ENTRY()) \param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together. used to link entries of this list together.
*/ */
#define AST_LIST_INSERT_TAIL(head, elm, type, field) do { \ #define AST_LIST_INSERT_TAIL(head, elm, field) do { \
struct type *curelm = (head)->first; \ typeof(elm) curelm = (head)->first; \
if(!curelm) { \ if (!curelm) { \
AST_LIST_INSERT_HEAD(head, elm, field); \ AST_LIST_INSERT_HEAD(head, elm, field); \
} else { \ } else { \
while ( curelm->field.next!=NULL ) { \ while (curelm->field.next!=NULL) { \
curelm=curelm->field.next; \ curelm=curelm->field.next; \
} \ } \
AST_LIST_INSERT_AFTER(curelm,elm,field); \ AST_LIST_INSERT_AFTER(curelm, elm, field); \
} \ } \
} while (0) } while (0)
/*! /*!
\brief Removes and returns the head entry from a list. \brief Removes and returns the head entry from a list.
\param head This is a pointer to the list head structure \param head This is a pointer to the list head structure
\param type This is the type of each list entry.
\param field This is the name of the field (declared using AST_LIST_ENTRY()) \param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together. used to link entries of this list together.
Removes the head entry from the list, and returns a pointer to it. The Removes the head entry from the list, and returns a pointer to it. The
forward-link pointer in the returned entry is \b not cleared. forward-link pointer in the returned entry is \b not cleared.
*/ */
#define AST_LIST_REMOVE_HEAD(head, type, field) ({ \ #define AST_LIST_REMOVE_HEAD(head, field) ({ \
struct type *cur = (head)->first; \ typeof((head)->first) cur = (head)->first; \
(head)->first = (head)->first->field.next; \ (head)->first = (head)->first->field.next; \
cur; \ cur; \
}) })
@@ -224,17 +266,16 @@ struct { \
\brief Removes a specific entry from a list. \brief Removes a specific entry from a list.
\param head This is a pointer to the list head structure \param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be removed. \param elm This is a pointer to the entry to be removed.
\param type This is the type of each list entry.
\param field This is the name of the field (declared using AST_LIST_ENTRY()) \param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together. used to link entries of this list together.
\warning The removed entry is \b not freed nor modified in any way. \warning The removed entry is \b not freed nor modified in any way.
*/ */
#define AST_LIST_REMOVE(head, elm, type, field) do { \ #define AST_LIST_REMOVE(head, elm, field) do { \
if ((head)->first == (elm)) { \ if ((head)->first == (elm)) { \
AST_LIST_REMOVE_HEAD((head), type, field); \ AST_LIST_REMOVE_HEAD((head), field); \
} \ } \
else { \ else { \
struct type *curelm = (head)->first; \ typeof(elm) curelm = (head)->first; \
while( curelm->field.next != (elm) ) \ while( curelm->field.next != (elm) ) \
curelm = curelm->field.next; \ curelm = curelm->field.next; \
curelm->field.next = \ curelm->field.next = \

4
pbx.c
View File

@@ -5052,7 +5052,7 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value
AST_LIST_TRAVERSE (headp, newvariable, entries) { AST_LIST_TRAVERSE (headp, newvariable, entries) {
if (strcasecmp(ast_var_name(newvariable), name) == 0) { if (strcasecmp(ast_var_name(newvariable), name) == 0) {
/* there is already such a variable, delete it */ /* there is already such a variable, delete it */
AST_LIST_REMOVE(headp, newvariable, ast_var_t, entries); AST_LIST_REMOVE(headp, newvariable, entries);
ast_var_delete(newvariable); ast_var_delete(newvariable);
break; break;
} }
@@ -5155,7 +5155,7 @@ void pbx_builtin_clear_globals(void)
{ {
struct ast_var_t *vardata; struct ast_var_t *vardata;
while (!AST_LIST_EMPTY(&globals)) { while (!AST_LIST_EMPTY(&globals)) {
vardata = AST_LIST_REMOVE_HEAD(&globals, ast_var_t, entries); vardata = AST_LIST_REMOVE_HEAD(&globals, entries);
ast_var_delete(vardata); ast_var_delete(vardata);
} }
} }

View File

@@ -551,7 +551,7 @@ static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map
AST_LIST_INSERT_HEAD(&headp, newvariable, entries); AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest)); pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */ while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */
newvariable = AST_LIST_REMOVE_HEAD(&headp, ast_var_t, entries); newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
ast_var_delete(newvariable); ast_var_delete(newvariable);
} }
} else } else

View File

@@ -81,7 +81,7 @@ static char *loopback_helper(char *buf, int buflen, const char *exten, const cha
pbx_substitute_variables_varshead(&headp, data, buf, buflen); pbx_substitute_variables_varshead(&headp, data, buf, buflen);
/* Substitute variables */ /* Substitute variables */
while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */ while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */
newvariable = AST_LIST_REMOVE_HEAD(&headp, ast_var_t, entries); newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
ast_var_delete(newvariable); ast_var_delete(newvariable);
} }
return buf; return buf;