String fields in structures. More...
#include "asterisk/inline_api.h"
Go to the source code of this file.
Data Structures | |
struct | ast_string_field_mgr |
struct | ast_string_field_pool |
Defines | |
#define | ast_calloc_with_stringfields(n, type, size) |
Allocate a structure with embedded stringfields in a single allocation. | |
#define | AST_DECLARE_STRING_FIELDS(field_list) |
Declare the fields needed in a structure. | |
#define | AST_STRING_FIELD(name) const ast_string_field name |
Declare a string field. | |
#define | AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - __alignof__(ast_string_field_allocation))) |
Macro to provide access to the allocation field that lives immediately in front of a string field. | |
#define | ast_string_field_build(x, field, fmt, args...) __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args) |
Set a field to a complex (built) value. | |
#define | ast_string_field_build_va(x, field, fmt, args1, args2) __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2) |
Set a field to a complex (built) value. | |
#define | ast_string_field_free_memory(x) __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
free all memory - to be called before destroying the object | |
#define | ast_string_field_init(x, size) __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
Initialize a field pool and fields. | |
#define | ast_string_field_ptr_build(x, ptr, fmt, args...) __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args) |
Set a field to a complex (built) value. | |
#define | ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2) |
Set a field to a complex (built) value with prebuilt va_lists. | |
#define | ast_string_field_ptr_set(x, ptr, data) |
Set a field to a simple string value. | |
#define | ast_string_field_set(x, field, data) |
Set a field to a simple string value. | |
Typedefs | |
typedef const char * | ast_string_field |
typedef uint16_t | ast_string_field_allocation |
Functions | |
void *attribute_malloc | __ast_calloc_with_stringfields (unsigned int num_structs, size_t struct_size, size_t field_mgr_offset, size_t field_mgr_pool_offset, size_t pool_size, const char *file, int lineno, const char *func) |
ast_string_field | __ast_string_field_alloc_space (struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, size_t needed) |
int | __ast_string_field_init (struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, int needed, const char *file, int lineno, const char *func) |
void | __ast_string_field_ptr_build (struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, ast_string_field *ptr, const char *format,...) |
void | __ast_string_field_ptr_build_va (struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, ast_string_field *ptr, const char *format, va_list a1, va_list a2) |
int | __ast_string_field_ptr_grow (struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, size_t needed, const ast_string_field *ptr) |
void | __ast_string_field_release_active (struct ast_string_field_pool *pool_head, const ast_string_field ptr) |
Variables | |
const char * | __ast_string_field_empty |
String fields in structures.
This file contains objects and macros used to manage string fields in structures without requiring them to be allocated as fixed-size buffers or requiring individual allocations for for each field.
Using this functionality is quite simple. An example structure with three fields is defined like this:
struct sample_fields { int x1; AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(foo); AST_STRING_FIELD(bar); AST_STRING_FIELD(blah); ); long x2; };
When an instance of this structure is allocated (either statically or dynamically), the fields and the pool of storage for them must be initialized:
struct sample_fields *x; x = ast_calloc(1, sizeof(*x)); if (x == NULL || ast_string_field_init(x, 252)) { if (x) ast_free(x); x = NULL; ... handle error }
Fields will default to pointing to an empty string, and will revert to that when ast_string_field_set() is called with a NULL argument. A string field will never contain NULL.
ast_string_field_init(x, 0) will reset fields to the initial value while keeping the pool allocated.
Reading the fields is much like using 'const char * const' fields in the structure: you cannot write to the field or to the memory it points to.
Writing to the fields must be done using the wrapper macros listed below; and assignments are always by value (i.e. strings are copied): ast_string_field_set() stores a simple value; ast_string_field_build() builds the string using a printf-style format; ast_string_field_build_va() is the varargs version of the above (for portability reasons it uses two vararg arguments); variants of these function allow passing a pointer to the field as an argument.
ast_string_field_set(x, foo, "infinite loop"); ast_string_field_set(x, foo, NULL); // set to an empty string ast_string_field_ptr_set(x, &x->bar, "right way"); ast_string_field_build(x, blah, "%d %s", zipcode, city); ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city); ast_string_field_build_va(x, bar, fmt, args1, args2) ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
When the structure instance is no longer needed, the fields and their storage pool must be freed:
ast_string_field_free_memory(x); ast_free(x);
This completes the API description.
Definition in file stringfields.h.
#define ast_calloc_with_stringfields | ( | n, | |||
type, | |||||
size | ) |
__ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \ size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
Allocate a structure with embedded stringfields in a single allocation.
n | Number of structures to allocate (see ast_calloc) | |
type | The type of structure to allocate | |
size | The number of bytes of space (minimum) to allocate for stringfields to use |
This function will allocate memory for one or more structures that use stringfields, and also allocate space for the stringfields and initialize the stringfield management structure embedded in the outer structure.
Definition at line 275 of file stringfields.h.
Referenced by append_mailbox_mapping(), ast_log(), AST_TEST_DEFINE(), build_extension(), build_profile(), jack_data_alloc(), load_config(), load_module(), raise_exception(), register_group(), register_group_feature(), sip_register(), and sip_subscribe_mwi().
#define AST_DECLARE_STRING_FIELDS | ( | field_list | ) |
struct ast_string_field_pool *__field_mgr_pool; \ field_list \ struct ast_string_field_mgr __field_mgr
Declare the fields needed in a structure.
field_list | The list of fields to declare, using AST_STRING_FIELD() for each one. Internally, string fields are stored as a pointer to the head of the pool, followed by individual string fields, and then a struct ast_string_field_mgr which describes the space allocated. We split the two variables so they can be used as markers around the field_list, and this allows us to determine how many entries are in the field, and play with them. In particular, for writing to the fields, we rely on __field_mgr_pool to be a non-const pointer, so we know it has the same size as ast_string_field, and we can use it to locate the fields. |
Definition at line 235 of file stringfields.h.
#define AST_STRING_FIELD | ( | name | ) | const ast_string_field name |
Declare a string field.
name | The field name |
Definition at line 220 of file stringfields.h.
#define AST_STRING_FIELD_ALLOCATION | ( | x | ) | *((ast_string_field_allocation *) (x - __alignof__(ast_string_field_allocation))) |
Macro to provide access to the allocation field that lives immediately in front of a string field.
x | Pointer to the string field |
Note that x must be a pointer to a byte-sized type -- normally (char *) -- or this calculation would break horribly
Definition at line 309 of file stringfields.h.
Referenced by __ast_string_field_alloc_space(), __ast_string_field_ptr_build_va(), __ast_string_field_ptr_grow(), and __ast_string_field_release_active().
#define ast_string_field_build | ( | x, | |||
field, | |||||
fmt, | |||||
args... | ) | __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args) |
Set a field to a complex (built) value.
x | Pointer to a structure containing fields | |
field | Name of the field to set | |
fmt | printf-style format string | |
args | Arguments for format string |
Definition at line 367 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), action_originate(), build_callid_pvt(), build_callid_registry(), build_contact(), build_localtag_registry(), build_profile(), build_user(), caldav_write_event(), handle_request_subscribe(), init_acf_query(), load_config(), make_our_tag(), parse_cdata(), parse_moved_contact(), parse_register_contact(), set_nonce_randdata(), sip_sendhtml(), sip_sipredirect(), and t30_phase_e_handler().
#define ast_string_field_build_va | ( | x, | |||
field, | |||||
fmt, | |||||
args1, | |||||
args2 | ) | __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2) |
Set a field to a complex (built) value.
x | Pointer to a structure containing fields | |
field | Name of the field to set | |
fmt | printf-style format string | |
args1 | argument one | |
args2 | argument two |
Definition at line 391 of file stringfields.h.
Referenced by __ast_channel_alloc_ap().
#define ast_string_field_free_memory | ( | x | ) | __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
free all memory - to be called before destroying the object
Definition at line 253 of file stringfields.h.
Referenced by __sip_destroy(), action_destroy(), ast_channel_destructor(), ast_custom_function_unregister(), ast_dummy_channel_destructor(), ast_pbx_outgoing_app(), ast_pbx_run_app(), AST_TEST_DEFINE(), ast_unregister_application(), ast_unregister_groups(), auth_http_callback(), build_user(), caldav_destructor(), calendar_destructor(), calendar_event_destructor(), delete_extension(), delete_file(), destroy_fast_originate_helper(), destroy_jack_data(), destroy_mailbox_mapping(), destroy_odbc(), destroy_queue(), destroy_session_details(), ewscal_destructor(), exception_store_free(), exchangecal_destructor(), free_acf_query(), free_outgoing(), icalendar_destructor(), load_module(), peer_destructor(), profile_destructor(), pvt_destructor(), realtime_multi_odbc(), realtime_odbc(), route_destructor(), sip_destroy_peer(), sip_monitor_instance_destructor(), sip_registry_destroy(), sip_subscribe_mwi_destroy(), sla_station_destructor(), sla_trunk_destructor(), store_odbc(), tds_unload_module(), temp_pvt_cleanup(), update_odbc(), and user_destructor().
#define ast_string_field_init | ( | x, | |||
size | ) | __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
Initialize a field pool and fields.
x | Pointer to a structure containing fields | |
size | Amount of storage to allocate. Use 0 to reset fields to the default value, and release all but the most recent pool. size<0 (used internally) means free all pools. |
Definition at line 249 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), __ast_dummy_channel_alloc(), acf_retrieve_docs(), action_originate(), alloc_queue(), ast_calendar_event_alloc(), ast_manager_register2(), ast_pbx_outgoing_app(), ast_register_application2(), auth_http_callback(), build_calendar(), build_peer(), build_profile(), build_route(), build_user(), caldav_load_calendar(), destroy_odbc(), ewscal_load_calendar(), exchangecal_load_calendar(), ical_load_calendar(), init_acf_query(), init_pvt(), new_iax(), new_outgoing(), realtime_multi_odbc(), realtime_odbc(), session_details_new(), sip_alloc(), sip_monitor_instance_init(), sla_build_station(), sla_build_trunk(), store_odbc(), tds_load_module(), temp_peer(), temp_pvt_init(), transmit_response_using_temp(), and update_odbc().
#define ast_string_field_ptr_build | ( | x, | |||
ptr, | |||||
fmt, | |||||
args... | ) | __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args) |
Set a field to a complex (built) value.
x | Pointer to a structure containing fields | |
ptr | Pointer to a field within the structure | |
fmt | printf-style format string | |
args | Arguments for format string |
Definition at line 356 of file stringfields.h.
#define ast_string_field_ptr_build_va | ( | x, | |||
ptr, | |||||
fmt, | |||||
args1, | |||||
args2 | ) | __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2) |
Set a field to a complex (built) value with prebuilt va_lists.
x | Pointer to a structure containing fields | |
ptr | Pointer to a field within the structure | |
fmt | printf-style format string | |
args1 | Arguments for format string in va_list format | |
args2 | a second copy of the va_list for the sake of bsd, with no va_list copy operation |
Definition at line 379 of file stringfields.h.
#define ast_string_field_ptr_set | ( | x, | |||
ptr, | |||||
data | ) |
Set a field to a simple string value.
x | Pointer to a structure containing fields | |
ptr | Pointer to a field within the structure | |
data | String value to be copied into the field |
Definition at line 318 of file stringfields.h.
Referenced by ast_parse_digest(), and reply_digest().
#define ast_string_field_set | ( | x, | |||
field, | |||||
data | ) |
do { \ ast_string_field_ptr_set(x, &(x)->field, data); \ } while (0)
Set a field to a simple string value.
x | Pointer to a structure containing fields | |
field | Name of the field to set | |
data | String value to be copied into the field |
Definition at line 344 of file stringfields.h.
Referenced by __ast_change_name_nolink(), __ast_channel_alloc_ap(), __find_callno(), __oh323_new(), __sip_subscribe_mwi_do(), acf_faxopt_write(), acf_retrieve_docs(), action_originate(), agent_new(), alloc_queue(), alsa_new(), analog_new_ast_channel(), append_mailbox_mapping(), apply_outgoing(), ast_call_forward(), ast_cdr_setaccount(), ast_cdr_setpeeraccount(), ast_cel_fabricate_channel_from_event(), ast_channel_change_linkedid(), ast_do_masquerade(), ast_iax2_new(), ast_log(), ast_manager_register2(), ast_parse_digest(), ast_pbx_outgoing_app(), ast_register_application2(), ast_set_hangupsource(), ast_set_owners_and_peers(), authenticate_reply(), authenticate_request(), authenticate_verify(), begin_dial_channel(), build_calendar(), build_extension(), build_peer(), build_profile(), build_route(), build_user(), cache_get_callno_locked(), caldav_add_event(), caldav_load_calendar(), calendar_write_exec(), change_callid_pvt(), check_access(), check_peer_ok(), check_user_full(), conf_start_moh(), console_new(), copy_event_data(), create_addr(), create_addr_from_peer(), custom_prepare(), dahdi_new(), dial_exec_full(), disa_exec(), do_forward(), endelm(), ewscal_load_calendar(), exchangecal_load_calendar(), extract_uri(), feature_request_and_dial(), findmeexec(), generic_fax_exec(), get_also_info(), get_destination(), get_pai(), get_realm(), get_rpid(), gtalk_new(), handle_cc_notify(), handle_incoming(), handle_options(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_publish(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_publish(), handle_response_register(), handle_response_subscribe(), iax2_call(), iax2_request(), iax_park(), ical_load_calendar(), icalendar_add_event(), init_acf_query(), init_pvt(), init_queue(), initreqprep(), jingle_new(), load_config(), load_module(), local_call(), logger_print_normal(), mgcp_new(), misdn_facility_ie_handler(), moh_handle_digit(), monitor_dial(), nbs_new(), new_iax(), new_outgoing(), oss_new(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), phone_new(), queue_set_param(), raise_exception(), read_config(), receivefax_exec(), reg_source_db(), register_group(), register_group_feature(), register_verify(), registry_authrequest(), reply_digest(), reqprep(), respprep(), ring_entry(), save_osptoken(), sendfax_exec(), set_moh_exec(), set_peer_defaults(), set_pvt_defaults(), sip_alloc(), sip_call(), sip_monitor_instance_init(), sip_new(), sip_park(), sip_parse_register_line(), sip_poke_peer(), sip_reload(), sip_request_call(), sip_send_mwi_to_peer(), sip_set_redirstr(), sip_subscribe_mwi(), skinny_new(), sla_build_station(), sla_build_trunk(), socket_process(), startelm(), store_callerid(), t30_phase_e_handler(), tds_load_module(), transmit_refer(), transmit_register(), transmit_response_using_temp(), unistim_new(), vm_execmain(), and wait_for_answer().
typedef const char* ast_string_field |
Definition at line 115 of file stringfields.h.
typedef uint16_t ast_string_field_allocation |
Definition at line 119 of file stringfields.h.
void* attribute_malloc __ast_calloc_with_stringfields | ( | unsigned int | num_structs, | |
size_t | struct_size, | |||
size_t | field_mgr_offset, | |||
size_t | field_mgr_pool_offset, | |||
size_t | pool_size, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 2026 of file utils.c.
References __ast_calloc(), allocation, ast_calloc, ast_string_field_pool::base, ast_string_field_mgr::embedded_pool, optimal_alloc_size(), ast_string_field_mgr::owner_file, ast_string_field_mgr::owner_func, ast_string_field_mgr::owner_line, and ast_string_field_pool::size.
02029 { 02030 struct ast_string_field_mgr *mgr; 02031 struct ast_string_field_pool *pool; 02032 struct ast_string_field_pool **pool_head; 02033 size_t pool_size_needed = sizeof(*pool) + pool_size; 02034 size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed); 02035 void *allocation; 02036 unsigned int x; 02037 02038 #if defined(__AST_DEBUG_MALLOC) 02039 if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) { 02040 return NULL; 02041 } 02042 #else 02043 if (!(allocation = ast_calloc(num_structs, size_to_alloc))) { 02044 return NULL; 02045 } 02046 #endif 02047 02048 for (x = 0; x < num_structs; x++) { 02049 void *base = allocation + (size_to_alloc * x); 02050 const char **p; 02051 02052 mgr = base + field_mgr_offset; 02053 pool_head = base + field_mgr_pool_offset; 02054 pool = base + struct_size; 02055 02056 p = (const char **) pool_head + 1; 02057 while ((struct ast_string_field_mgr *) p != mgr) { 02058 *p++ = __ast_string_field_empty; 02059 } 02060 02061 mgr->embedded_pool = pool; 02062 *pool_head = pool; 02063 pool->size = size_to_alloc - struct_size - sizeof(*pool); 02064 #if defined(__AST_DEBUG_MALLOC) 02065 mgr->owner_file = file; 02066 mgr->owner_func = func; 02067 mgr->owner_line = lineno; 02068 #endif 02069 } 02070 02071 return allocation; 02072 }
ast_string_field __ast_string_field_alloc_space | ( | struct ast_string_field_mgr * | mgr, | |
struct ast_string_field_pool ** | pool_head, | |||
size_t | needed | |||
) |
Definition at line 1847 of file utils.c.
References add_string_pool(), ast_alignof, ast_assert, ast_make_room_for, AST_STRING_FIELD_ALLOCATION, ast_string_field_mgr::last_alloc, ast_string_field_mgr::owner_file, ast_string_field_mgr::owner_func, and ast_string_field_mgr::owner_line.
Referenced by __ast_string_field_ptr_build_va().
01849 { 01850 char *result = NULL; 01851 size_t space = (*pool_head)->size - (*pool_head)->used; 01852 size_t to_alloc; 01853 01854 /* Make room for ast_string_field_allocation and make it a multiple of that. */ 01855 to_alloc = ast_make_room_for(needed, ast_string_field_allocation); 01856 ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0); 01857 01858 if (__builtin_expect(to_alloc > space, 0)) { 01859 size_t new_size = (*pool_head)->size; 01860 01861 while (new_size < to_alloc) { 01862 new_size *= 2; 01863 } 01864 01865 #if defined(__AST_DEBUG_MALLOC) 01866 if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func)) 01867 return NULL; 01868 #else 01869 if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__)) 01870 return NULL; 01871 #endif 01872 } 01873 01874 /* pool->base is always aligned (gcc aligned attribute). We ensure that 01875 * to_alloc is also a multiple of ast_alignof(ast_string_field_allocation) 01876 * causing result to always be aligned as well; which in turn fixes that 01877 * AST_STRING_FIELD_ALLOCATION(result) is aligned. */ 01878 result = (*pool_head)->base + (*pool_head)->used; 01879 (*pool_head)->used += to_alloc; 01880 (*pool_head)->active += needed; 01881 result += ast_alignof(ast_string_field_allocation); 01882 AST_STRING_FIELD_ALLOCATION(result) = needed; 01883 mgr->last_alloc = result; 01884 01885 return result; 01886 }
int __ast_string_field_init | ( | struct ast_string_field_mgr * | mgr, | |
struct ast_string_field_pool ** | pool_head, | |||
int | needed, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 1780 of file utils.c.
References ast_string_field_pool::active, add_string_pool(), ast_free, ast_log(), ast_string_field_mgr::embedded_pool, ast_string_field_mgr::last_alloc, LOG_WARNING, ast_string_field_mgr::owner_file, ast_string_field_mgr::owner_func, ast_string_field_mgr::owner_line, ast_string_field_pool::prev, and ast_string_field_pool::used.
01782 { 01783 const char **p = (const char **) pool_head + 1; 01784 struct ast_string_field_pool *cur = NULL; 01785 struct ast_string_field_pool *preserve = NULL; 01786 01787 /* clear fields - this is always necessary */ 01788 while ((struct ast_string_field_mgr *) p != mgr) { 01789 *p++ = __ast_string_field_empty; 01790 } 01791 01792 mgr->last_alloc = NULL; 01793 #if defined(__AST_DEBUG_MALLOC) 01794 mgr->owner_file = file; 01795 mgr->owner_func = func; 01796 mgr->owner_line = lineno; 01797 #endif 01798 if (needed > 0) { /* allocate the initial pool */ 01799 *pool_head = NULL; 01800 mgr->embedded_pool = NULL; 01801 return add_string_pool(mgr, pool_head, needed, file, lineno, func); 01802 } 01803 01804 /* if there is an embedded pool, we can't actually release *all* 01805 * pools, we must keep the embedded one. if the caller is about 01806 * to free the structure that contains the stringfield manager 01807 * and embedded pool anyway, it will be freed as part of that 01808 * operation. 01809 */ 01810 if ((needed < 0) && mgr->embedded_pool) { 01811 needed = 0; 01812 } 01813 01814 if (needed < 0) { /* reset all pools */ 01815 cur = *pool_head; 01816 } else if (mgr->embedded_pool) { /* preserve the embedded pool */ 01817 preserve = mgr->embedded_pool; 01818 cur = *pool_head; 01819 } else { /* preserve the last pool */ 01820 if (*pool_head == NULL) { 01821 ast_log(LOG_WARNING, "trying to reset empty pool\n"); 01822 return -1; 01823 } 01824 preserve = *pool_head; 01825 cur = preserve->prev; 01826 } 01827 01828 if (preserve) { 01829 preserve->prev = NULL; 01830 preserve->used = preserve->active = 0; 01831 } 01832 01833 while (cur) { 01834 struct ast_string_field_pool *prev = cur->prev; 01835 01836 if (cur != preserve) { 01837 ast_free(cur); 01838 } 01839 cur = prev; 01840 } 01841 01842 *pool_head = preserve; 01843 01844 return 0; 01845 }
void __ast_string_field_ptr_build | ( | struct ast_string_field_mgr * | mgr, | |
struct ast_string_field_pool ** | pool_head, | |||
ast_string_field * | ptr, | |||
const char * | format, | |||
... | ||||
) |
Definition at line 2011 of file utils.c.
References __ast_string_field_ptr_build_va().
02014 { 02015 va_list ap1, ap2; 02016 02017 va_start(ap1, format); 02018 va_start(ap2, format); /* va_copy does not exist on FreeBSD */ 02019 02020 __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap1, ap2); 02021 02022 va_end(ap1); 02023 va_end(ap2); 02024 }
void __ast_string_field_ptr_build_va | ( | struct ast_string_field_mgr * | mgr, | |
struct ast_string_field_pool ** | pool_head, | |||
ast_string_field * | ptr, | |||
const char * | format, | |||
va_list | a1, | |||
va_list | a2 | |||
) |
Definition at line 1935 of file utils.c.
References __ast_string_field_alloc_space(), __ast_string_field_release_active(), ast_align_for, ast_alignof, ast_assert, ast_make_room_for, AST_STRING_FIELD_ALLOCATION, available(), and ast_string_field_mgr::last_alloc.
Referenced by __ast_string_field_ptr_build().
01938 { 01939 size_t needed; 01940 size_t available; 01941 size_t space = (*pool_head)->size - (*pool_head)->used; 01942 int res; 01943 ssize_t grow; 01944 char *target; 01945 01946 /* if the field already has space allocated, try to reuse it; 01947 otherwise, try to use the empty space at the end of the current 01948 pool 01949 */ 01950 if (*ptr != __ast_string_field_empty) { 01951 target = (char *) *ptr; 01952 available = AST_STRING_FIELD_ALLOCATION(*ptr); 01953 if (*ptr == mgr->last_alloc) { 01954 available += space; 01955 } 01956 } else { 01957 /* pool->used is always a multiple of ast_alignof(ast_string_field_allocation) 01958 * so we don't need to re-align anything here. 01959 */ 01960 target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation); 01961 if (space > ast_alignof(ast_string_field_allocation)) { 01962 available = space - ast_alignof(ast_string_field_allocation); 01963 } else { 01964 available = 0; 01965 } 01966 } 01967 01968 res = vsnprintf(target, available, format, ap1); 01969 if (res < 0) { 01970 /* Are we out of memory? */ 01971 return; 01972 } 01973 if (res == 0) { 01974 __ast_string_field_release_active(*pool_head, *ptr); 01975 *ptr = __ast_string_field_empty; 01976 return; 01977 } 01978 needed = (size_t)res + 1; /* NUL byte */ 01979 01980 if (needed > available) { 01981 /* the allocation could not be satisfied using the field's current allocation 01982 (if it has one), or the space available in the pool (if it does not). allocate 01983 space for it, adding a new string pool if necessary. 01984 */ 01985 if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) { 01986 return; 01987 } 01988 vsprintf(target, format, ap2); 01989 __ast_string_field_release_active(*pool_head, *ptr); 01990 *ptr = target; 01991 } else if (*ptr != target) { 01992 /* the allocation was satisfied using available space in the pool, but not 01993 using the space already allocated to the field 01994 */ 01995 __ast_string_field_release_active(*pool_head, *ptr); 01996 mgr->last_alloc = *ptr = target; 01997 ast_assert(needed < (ast_string_field_allocation)-1); 01998 AST_STRING_FIELD_ALLOCATION(target) = (ast_string_field_allocation)needed; 01999 (*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation); 02000 (*pool_head)->active += needed; 02001 } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) { 02002 /* the allocation was satisfied by using available space in the pool *and* 02003 the field was the last allocated field from the pool, so it grew 02004 */ 02005 AST_STRING_FIELD_ALLOCATION(*ptr) += grow; 02006 (*pool_head)->used += ast_align_for(grow, ast_string_field_allocation); 02007 (*pool_head)->active += grow; 02008 } 02009 }
int __ast_string_field_ptr_grow | ( | struct ast_string_field_mgr * | mgr, | |
struct ast_string_field_pool ** | pool_head, | |||
size_t | needed, | |||
const ast_string_field * | ptr | |||
) |
Definition at line 1888 of file utils.c.
References AST_STRING_FIELD_ALLOCATION, and ast_string_field_mgr::last_alloc.
01891 { 01892 ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr); 01893 size_t space = (*pool_head)->size - (*pool_head)->used; 01894 01895 if (*ptr != mgr->last_alloc) { 01896 return 1; 01897 } 01898 01899 if (space < grow) { 01900 return 1; 01901 } 01902 01903 (*pool_head)->used += grow; 01904 (*pool_head)->active += grow; 01905 AST_STRING_FIELD_ALLOCATION(*ptr) += grow; 01906 01907 return 0; 01908 }
void __ast_string_field_release_active | ( | struct ast_string_field_pool * | pool_head, | |
const ast_string_field | ptr | |||
) |
Definition at line 1910 of file utils.c.
References ast_string_field_pool::active, ast_free, AST_STRING_FIELD_ALLOCATION, and ast_string_field_pool::prev.
Referenced by __ast_string_field_ptr_build_va().
01912 { 01913 struct ast_string_field_pool *pool, *prev; 01914 01915 if (ptr == __ast_string_field_empty) { 01916 return; 01917 } 01918 01919 for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) { 01920 if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) { 01921 pool->active -= AST_STRING_FIELD_ALLOCATION(ptr); 01922 if (pool->active == 0) { 01923 if (prev) { 01924 prev->prev = pool->prev; 01925 ast_free(pool); 01926 } else { 01927 pool->used = 0; 01928 } 01929 } 01930 break; 01931 } 01932 } 01933 }
const char* __ast_string_field_empty |