Sat Apr 26 2014 22:01:42

Asterisk developer's documentation


stringfields.h
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2006, Digium, Inc.
00005  *
00006  * Kevin P. Fleming <kpfleming@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020   \brief String fields in structures
00021 
00022   This file contains objects and macros used to manage string
00023   fields in structures without requiring them to be allocated
00024   as fixed-size buffers or requiring individual allocations for
00025   for each field.
00026 
00027   Using this functionality is quite simple. An example structure
00028   with three fields is defined like this:
00029   
00030   \code
00031   struct sample_fields {
00032      int x1;
00033      AST_DECLARE_STRING_FIELDS(
00034         AST_STRING_FIELD(foo);
00035         AST_STRING_FIELD(bar);
00036         AST_STRING_FIELD(blah);
00037      );
00038      long x2;
00039   };
00040   \endcode
00041   
00042   When an instance of this structure is allocated (either statically or
00043   dynamically), the fields and the pool of storage for them must be
00044   initialized:
00045   
00046   \code
00047   struct sample_fields *x;
00048   
00049   x = ast_calloc(1, sizeof(*x));
00050   if (x == NULL || ast_string_field_init(x, 252)) {
00051    if (x)
00052       ast_free(x);
00053    x = NULL;
00054    ... handle error
00055   }
00056   \endcode
00057 
00058   Fields will default to pointing to an empty string, and will revert to
00059   that when ast_string_field_set() is called with a NULL argument.
00060   A string field will \b never contain NULL.
00061 
00062   ast_string_field_init(x, 0) will reset fields to the
00063   initial value while keeping the pool allocated.
00064   
00065   Reading the fields is much like using 'const char * const' fields in the
00066   structure: you cannot write to the field or to the memory it points to.
00067 
00068   Writing to the fields must be done using the wrapper macros listed below;
00069   and assignments are always by value (i.e. strings are copied):
00070   * ast_string_field_set() stores a simple value;
00071   * ast_string_field_build() builds the string using a printf-style format;
00072   * ast_string_field_build_va() is the varargs version of the above;
00073   * variants of these function allow passing a pointer to the field
00074     as an argument.
00075 
00076   \code
00077   ast_string_field_set(x, foo, "infinite loop");
00078   ast_string_field_set(x, foo, NULL); // set to an empty string
00079   ast_string_field_ptr_set(x, &x->bar, "right way");
00080 
00081   ast_string_field_build(x, blah, "%d %s", zipcode, city);
00082   ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
00083 
00084   ast_string_field_build_va(x, bar, fmt, args)
00085   ast_string_field_ptr_build_va(x, &x->bar, fmt, args)
00086   \endcode
00087 
00088   When the structure instance is no longer needed, the fields
00089   and their storage pool must be freed:
00090   
00091   \code
00092   ast_string_field_free_memory(x);
00093   ast_free(x);
00094   \endcode
00095 
00096   This completes the API description.
00097 */
00098 
00099 #ifndef _ASTERISK_STRINGFIELDS_H
00100 #define _ASTERISK_STRINGFIELDS_H
00101 
00102 #include "asterisk/inline_api.h"
00103 
00104 /*!
00105   \internal
00106   \brief An opaque type for managed string fields in structures
00107 
00108   Don't declare instances of this type directly; use the AST_STRING_FIELD()
00109   macro instead.
00110 
00111   In addition to the string itself, the amount of space allocated for the
00112   field is stored in the two bytes immediately preceding it.
00113 */
00114 typedef const char * ast_string_field;
00115 
00116 /* the type of storage used to track how many bytes were allocated for a field */
00117 
00118 typedef uint16_t ast_string_field_allocation;
00119 
00120 /*!
00121   \internal
00122   \brief A constant empty string used for fields that have no other value
00123 */
00124 extern const char *__ast_string_field_empty;
00125 
00126 /*!
00127   \internal
00128   \brief Structure used to hold a pool of space for string fields
00129   \note base is aligned so base+used can stay aligned by incrementing used with
00130         aligned numbers only
00131 */
00132 struct ast_string_field_pool {
00133    struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
00134    size_t size;            /*!< the total size of the pool */
00135    size_t used;            /*!< the space used in the pool */
00136    size_t active;          /*!< the amount of space actively in use by fields */
00137    char base[0] __attribute__((aligned(__alignof__(ast_string_field_allocation)))); /*!< storage space for the fields */
00138 };
00139 
00140 /*!
00141   \internal
00142   \brief Structure used to manage the storage for a set of string fields.
00143 */
00144 struct ast_string_field_mgr {
00145    ast_string_field last_alloc;        /*!< the last field allocated */
00146    struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */
00147 #if defined(__AST_DEBUG_MALLOC)
00148    const char *owner_file;          /*!< filename of owner */
00149    const char *owner_func;          /*!< function name of owner */
00150    int owner_line;               /*!< line number of owner */
00151 #endif
00152 };
00153 
00154 /*!
00155   \internal
00156   \brief Attempt to 'grow' an already allocated field to a larger size
00157   \param mgr Pointer to the pool manager structure
00158   \param needed Amount of space needed for this field
00159   \param ptr Pointer to a field within the structure
00160   \return 0 on success, non-zero on failure
00161 
00162   This function will attempt to increase the amount of space allocated to
00163   an existing field to the amount requested; this is only possible if the
00164   field was the last field allocated from the current storage pool and
00165   the pool has enough space available. If so, the additional space will be
00166   allocated to this field and the field's address will not be changed.
00167 */
00168 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
00169             struct ast_string_field_pool **pool_head, size_t needed,
00170             const ast_string_field *ptr);
00171 
00172 /*!
00173   \internal
00174   \brief Allocate space for a field
00175   \param mgr Pointer to the pool manager structure
00176   \param needed Amount of space needed for this field
00177   \param fields Pointer to the first entry of the field array
00178   \return NULL on failure, an address for the field on success.
00179 
00180   This function will allocate the requested amount of space from
00181   the field pool. If the requested amount of space is not available,
00182   an additional pool will be allocated.
00183 */
00184 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
00185                   struct ast_string_field_pool **pool_head, size_t needed);
00186 
00187 /*!
00188   \internal
00189   \brief Set a field to a complex (built) value
00190   \param mgr Pointer to the pool manager structure
00191   \param pool_head Pointer to the current pool
00192   \param ptr Pointer to a field within the structure
00193   \param format printf-style format string
00194   \return nothing
00195 */
00196 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
00197               struct ast_string_field_pool **pool_head,
00198               ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
00199 
00200 /*!
00201   \internal
00202   \brief Set a field to a complex (built) value
00203   \param mgr Pointer to the pool manager structure
00204   \param pool_head Pointer to the current pool
00205   \param ptr Pointer to a field within the structure
00206   \param format printf-style format string
00207   \param args va_list of the args for the format_string
00208   \return nothing
00209 */
00210 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
00211                  struct ast_string_field_pool **pool_head,
00212                  ast_string_field *ptr, const char *format, va_list ap) __attribute__((format(printf, 4, 0)));
00213 
00214 /*!
00215   \brief Declare a string field
00216   \param name The field name
00217 */
00218 #define AST_STRING_FIELD(name) const ast_string_field name
00219 
00220 /*!
00221   \brief Declare the fields needed in a structure
00222   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
00223   Internally, string fields are stored as a pointer to the head of the pool,
00224   followed by individual string fields, and then a struct ast_string_field_mgr
00225   which describes the space allocated.
00226   We split the two variables so they can be used as markers around the
00227   field_list, and this allows us to determine how many entries are in
00228   the field, and play with them.
00229   In particular, for writing to the fields, we rely on __field_mgr_pool to be
00230   a non-const pointer, so we know it has the same size as ast_string_field,
00231   and we can use it to locate the fields.
00232 */
00233 #define AST_DECLARE_STRING_FIELDS(field_list) \
00234    struct ast_string_field_pool *__field_mgr_pool; \
00235    field_list              \
00236    struct ast_string_field_mgr __field_mgr
00237 
00238 /*!
00239   \brief Initialize a field pool and fields
00240   \param x Pointer to a structure containing fields
00241   \param size Amount of storage to allocate.
00242    Use 0 to reset fields to the default value,
00243    and release all but the most recent pool.
00244    size<0 (used internally) means free all pools.
00245   \return 0 on success, non-zero on failure
00246 */
00247 #define ast_string_field_init(x, size) \
00248    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00249 
00250 /*! \brief free all memory - to be called before destroying the object */
00251 #define ast_string_field_free_memory(x)   \
00252    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00253 
00254 /*!
00255  * \internal
00256  * \brief internal version of ast_string_field_init
00257  */
00258 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
00259              int needed, const char *file, int lineno, const char *func);
00260 
00261 /*!
00262  * \brief Allocate a structure with embedded stringfields in a single allocation
00263  * \param n Number of structures to allocate (see ast_calloc)
00264  * \param type The type of structure to allocate
00265  * \param size The number of bytes of space (minimum) to allocate for stringfields to use
00266  *
00267  * This function will allocate memory for one or more structures that use stringfields, and
00268  * also allocate space for the stringfields and initialize the stringfield management
00269  * structure embedded in the outer structure.
00270  *
00271  * \since 1.8
00272  */
00273 #define ast_calloc_with_stringfields(n, type, size) \
00274    __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
00275                    size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00276 
00277 /*!
00278  * \internal
00279  * \brief internal version of ast_calloc_with_stringfields
00280  */
00281 void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
00282                          size_t field_mgr_pool_offset, size_t pool_size, const char *file,
00283                          int lineno, const char *func);
00284 
00285 /*!
00286   \internal
00287   \brief Release a field's allocation from a pool
00288   \param pool_head Pointer to the current pool
00289   \param ptr Field to be released
00290   \return nothing
00291 
00292   This function will search the pool list to find the pool that contains
00293   the allocation for the specified field, then remove the field's allocation
00294   from that pool's 'active' count. If the pool's active count reaches zero,
00295   and it is not the current pool, then it will be freed.
00296  */
00297 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
00298                    const ast_string_field ptr);
00299 
00300 /*!
00301   \brief Macro to provide access to the allocation field that lives immediately in front of a string field
00302   \param x Pointer to the string field
00303 
00304   Note that x must be a pointer to a byte-sized type -- normally (char *) -- or this calculation
00305   would break horribly
00306 */
00307 #define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - __alignof__(ast_string_field_allocation)))
00308 
00309 /*!
00310   \brief Set a field to a simple string value
00311   \param x Pointer to a structure containing fields
00312   \param ptr Pointer to a field within the structure
00313   \param data String value to be copied into the field
00314   \return nothing
00315 */
00316 #define ast_string_field_ptr_set(x, ptr, data) ast_string_field_ptr_set_by_fields((x)->__field_mgr_pool, (x)->__field_mgr, ptr, data)
00317 
00318 #define ast_string_field_ptr_set_by_fields(field_mgr_pool, field_mgr, ptr, data) do {                                   \
00319     const char *__d__ = (data);                                         \
00320     size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;                              \
00321     ast_string_field *__p__ = (ast_string_field *) (ptr);                               \
00322     if (__dlen__ == 1) {                                                \
00323         __ast_string_field_release_active(field_mgr_pool, *__p__);                  \
00324         *__p__ = __ast_string_field_empty;                                  \
00325     } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) ||                         \
00326            (!__ast_string_field_ptr_grow(&field_mgr, &field_mgr_pool, __dlen__, __p__)) ||   \
00327            (*__p__ = __ast_string_field_alloc_space(&field_mgr, &field_mgr_pool, __dlen__))) {   \
00328         if (*__p__ != (*ptr)) {                                         \
00329             __ast_string_field_release_active(field_mgr_pool, (*ptr));              \
00330         }                                                   \
00331         memcpy(* (void **) __p__, __d__, __dlen__);                             \
00332     }                                                       \
00333     } while (0)
00334 
00335 /*!
00336   \brief Set a field to a simple string value
00337   \param x Pointer to a structure containing fields
00338   \param field Name of the field to set
00339   \param data String value to be copied into the field
00340   \return nothing
00341 */
00342 #define ast_string_field_set(x, field, data) do {     \
00343    ast_string_field_ptr_set(x, &(x)->field, data);    \
00344    } while (0)
00345 
00346 /*!
00347   \brief Set a field to a complex (built) value
00348   \param x Pointer to a structure containing fields
00349   \param ptr Pointer to a field within the structure
00350   \param fmt printf-style format string
00351   \param args Arguments for format string
00352   \return nothing
00353 */
00354 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
00355    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
00356 
00357 /*!
00358   \brief Set a field to a complex (built) value
00359   \param x Pointer to a structure containing fields
00360   \param field Name of the field to set
00361   \param fmt printf-style format string
00362   \param args Arguments for format string
00363   \return nothing
00364 */
00365 #define ast_string_field_build(x, field, fmt, args...) \
00366    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
00367 
00368 /*!
00369   \brief Set a field to a complex (built) value with prebuilt va_lists.
00370   \param x Pointer to a structure containing fields
00371   \param ptr Pointer to a field within the structure
00372   \param fmt printf-style format string
00373   \param args Arguments for format string in va_list format
00374   \return nothing
00375 */
00376 #define ast_string_field_ptr_build_va(x, ptr, fmt, args) \
00377    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
00378 
00379 /*!
00380   \brief Set a field to a complex (built) value
00381   \param x Pointer to a structure containing fields
00382   \param field Name of the field to set
00383   \param fmt printf-style format string
00384   \param args Arguments for format string in va_list format
00385   \return nothing
00386 */
00387 #define ast_string_field_build_va(x, field, fmt, args) \
00388    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
00389 
00390 #endif /* _ASTERISK_STRINGFIELDS_H */