/*! * \brief Internal cleanup function * \internal * \param mgr * \param pool_head * \param cleanup_type * 0: Reset all string fields and free all pools except the last or embedded pool. * Keep the internal management structures so the structure can be reused. * -1: Reset all string fields and free all pools except the embedded pool. * Free the internal management structures. * \param file * \param lineno * \param func * * \retval 0 Success * \retval -1 Failure */ int __ast_string_field_free_memory(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, enum ast_stringfield_cleanup_type cleanup_type, const char *file, int lineno, const char *func) { struct ast_string_field_pool *cur = NULL; struct ast_string_field_pool *preserve = NULL; /* reset all the fields regardless of cleanup type */ AST_VECTOR_CALLBACK_VOID(&mgr->string_fields, reset_field); switch (cleanup_type) { case AST_STRINGFIELD_DESTROY: AST_VECTOR_FREE(&mgr->string_fields); if (mgr->embedded_pool) { /* ALWAYS preserve the embedded pool if there is one */ preserve = mgr->embedded_pool; preserve->used = preserve->active = 0; } break; case AST_STRINGFIELD_RESET: /* Preserve the embedded pool if there is one, otherwise the last pool */ if (mgr->embedded_pool) { preserve = mgr->embedded_pool; } else { if (*pool_head == NULL) { ast_log(LOG_WARNING, "trying to reset empty pool\n"); return -1; } preserve = *pool_head; } preserve->used = preserve->active = 0; break; default: return -1; } cur = *pool_head; while (cur) { struct ast_string_field_pool *prev = cur->prev; if (cur != preserve) { ast_free(cur); } cur = prev; } *pool_head = preserve; if (preserve) { preserve->prev = NULL; } return 0; }
void __ast_bt_free_symbols(struct ast_vector_string *symbols) { AST_VECTOR_CALLBACK_VOID(symbols, free); AST_VECTOR_PTR_FREE(symbols); }