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_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_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 |
Functions | |
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, size_t needed, 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 (this feature is not used in this code, but comes from external requirements).
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 (XXX perhaps the latter is too much of a restriction since values are not shared).
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; ast_string_field_build_va() is the varargs version of the above (for portability reasons it uses two vararg); 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_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 227 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 212 of file stringfields.h.
#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 308 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), build_callid_pvt(), build_callid_registry(), build_contact(), build_profile(), build_rpid(), build_user(), create_addr_from_peer(), handle_request_subscribe(), handle_response(), init_acf_query(), mgcp_new(), parse_moved_contact(), parse_register_contact(), set_nonce_randdata(), sip_sendhtml(), sip_sipredirect(), and unistim_new().
#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 332 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 245 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), __sip_destroy(), ast_channel_free(), ast_custom_function_unregister(), ast_unregister_application(), ast_unregister_groups(), build_user(), delete_extension(), delete_file(), destroy_jack_data(), destroy_mailbox_mapping(), destroy_station(), destroy_trunk(), exception_store_free(), free_acf_query(), free_outgoing(), init_acf_query(), load_module(), peer_destructor(), profile_destructor(), pvt_destructor(), realtime_multi_odbc(), realtime_odbc(), route_destructor(), sip_destroy_peer(), sip_registry_destroy(), sip_subscribe_mwi_destroy(), 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 241 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), acf_retrieve_docs(), append_mailbox_mapping(), ast_register_application2(), build_extension(), build_peer(), build_profile(), build_route(), build_user(), init_acf_query(), init_outgoing(), init_pvt(), jack_data_alloc(), load_module(), new_iax(), pbx_builtin_raise_exception(), realtime_multi_odbc(), realtime_odbc(), register_group(), register_group_feature(), sip_alloc(), sip_register(), sip_subscribe_mwi(), sla_build_station(), sla_build_trunk(), 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 297 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 320 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 262 of file stringfields.h.
Referenced by 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 285 of file stringfields.h.
Referenced by __ast_channel_alloc_ap(), __find_callno(), __oh323_new(), __sip_subscribe_mwi_do(), acf_retrieve_docs(), agent_new(), alsa_new(), append_mailbox_mapping(), apply_outgoing(), ast_call_forward(), ast_cdr_setaccount(), ast_change_name(), ast_do_masquerade(), ast_iax2_new(), ast_register_application2(), authenticate_reply(), authenticate_request(), authenticate_verify(), begin_dial_channel(), build_extension(), build_peer(), build_profile(), build_route(), build_rpid(), build_user(), cache_get_callno_locked(), check_access(), check_peer_ok(), check_user_full(), conf_start_moh(), console_new(), create_addr(), create_addr_from_peer(), custom_prepare(), dahdi_new(), dial_exec_full(), disa_exec(), do_forward(), extract_uri(), feature_request_and_dial(), findmeexec(), get_also_info(), get_destination(), get_rdnis(), gtalk_new(), handle_incoming(), handle_options(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_subscribe(), iax2_call(), iax2_request(), init_acf_query(), init_pvt(), initreqprep(), jingle_new(), load_module(), local_call(), mgcp_new(), moh_handle_digit(), monitor_dial(), nbs_new(), new_iax(), oss_new(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), pbx_builtin_raise_exception(), phone_new(), read_config(), reg_source_db(), register_group(), register_group_feature(), register_verify(), registry_authrequest(), replace_cid(), reply_digest(), reqprep(), respprep(), ring_entry(), save_osptoken(), set_moh_exec(), set_peer_defaults(), set_pvt_defaults(), sip_alloc(), sip_call(), sip_new(), sip_park(), sip_poke_peer(), sip_register(), sip_request_call(), sip_set_redirstr(), sip_subscribe_mwi(), skinny_new(), sla_build_station(), sla_build_trunk(), socket_process(), store_callerid(), tds_load_module(), transmit_refer(), transmit_register(), transmit_response_using_temp(), unistim_new(), usbradio_new(), vm_execmain(), and wait_for_answer().
typedef const char* ast_string_field |
Definition at line 114 of file stringfields.h.
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 1570 of file utils.c.
References add_string_pool(), ast_string_field_mgr::last_alloc, ast_string_field_mgr::size, and ast_string_field_mgr::used.
{ char *result = NULL; size_t space = mgr->size - mgr->used; if (__builtin_expect(needed > space, 0)) { size_t new_size = mgr->size * 2; while (new_size < needed) new_size *= 2; #if defined(__AST_DEBUG_MALLOC) if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func)) return NULL; #else if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__)) return NULL; #endif } result = (*pool_head)->base + mgr->used; mgr->used += needed; mgr->last_alloc = result; return result; }
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 1516 of file utils.c.
References __ast_string_field_empty, add_string_pool(), ast_free, ast_log(), ast_string_field_mgr::last_alloc, LOG_WARNING, ast_string_field_pool::prev, and ast_string_field_mgr::used.
{ const char **p = (const char **) pool_head + 1; struct ast_string_field_pool *cur = NULL; struct ast_string_field_pool *preserve = NULL; /* clear fields - this is always necessary */ while ((struct ast_string_field_mgr *) p != mgr) *p++ = __ast_string_field_empty; mgr->last_alloc = NULL; #if defined(__AST_DEBUG_MALLOC) mgr->owner_file = file; mgr->owner_func = func; mgr->owner_line = lineno; #endif if (needed > 0) { /* allocate the initial pool */ *pool_head = NULL; return add_string_pool(mgr, pool_head, needed, file, lineno, func); } if (needed < 0) { /* reset all pools */ if (*pool_head == NULL) { ast_log(LOG_WARNING, "trying to reset empty pool\n"); return -1; } cur = *pool_head; } else { /* preserve the last pool */ if (*pool_head == NULL) { ast_log(LOG_WARNING, "trying to reset empty pool\n"); return -1; } mgr->used = 0; preserve = *pool_head; cur = preserve->prev; } if (preserve) { preserve->prev = NULL; } while (cur) { struct ast_string_field_pool *prev = cur->prev; if (cur != preserve) { ast_free(cur); } cur = prev; } *pool_head = preserve; return 0; }
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 1676 of file utils.c.
References __ast_string_field_ptr_build_va().
{ va_list ap1, ap2; va_start(ap1, format); va_start(ap2, format); /* va_copy does not exist on FreeBSD */ __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap1, ap2); va_end(ap1); va_end(ap2); }
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 1620 of file utils.c.
References add_string_pool(), available(), ast_string_field_mgr::last_alloc, ast_string_field_mgr::size, and ast_string_field_mgr::used.
Referenced by __ast_string_field_ptr_build().
{ size_t needed; size_t available; size_t space = mgr->size - mgr->used; char *target; /* if the field already has space allocated, try to reuse it; otherwise, use the empty space at the end of the current pool */ if ((*ptr)[0] != '\0') { target = (char *) *ptr; available = strlen(target) + 1; } else { target = (*pool_head)->base + mgr->used; available = space; } needed = vsnprintf(target, available, format, ap1) + 1; va_end(ap1); if (needed > available) { /* if the space needed can be satisfied by using the current pool (which could only occur if we tried to use the field's allocated space and failed), then use that space; otherwise allocate a new pool */ if (needed > space) { size_t new_size = mgr->size * 2; while (new_size < needed) new_size *= 2; #if defined(__AST_DEBUG_MALLOC) if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func)) return; #else if (add_string_pool(mgr, pool_head, new_size, NULL, 0, NULL)) return; #endif } target = (*pool_head)->base + mgr->used; vsprintf(target, format, ap2); } if (*ptr != target) { mgr->last_alloc = *ptr = target; mgr->used += needed; } }
int __ast_string_field_ptr_grow | ( | struct ast_string_field_mgr * | mgr, |
size_t | needed, | ||
const ast_string_field * | ptr | ||
) |
Definition at line 1597 of file utils.c.
References ast_string_field_mgr::last_alloc, ast_string_field_mgr::size, and ast_string_field_mgr::used.
{ int grow = needed - (strlen(*ptr) + 1); size_t space = mgr->size - mgr->used; if (grow <= 0) { return 0; } if (*ptr != mgr->last_alloc) { return 1; } if (space < grow) { return 1; } mgr->used += grow; return 0; }
const char __ast_string_field_empty[] |