Wed Apr 6 11:29:48 2011

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 (for
00073     portability reasons it uses two vararg arguments);
00074   * variants of these function allow passing a pointer to the field
00075     as an argument.
00076 
00077   \code
00078   ast_string_field_set(x, foo, "infinite loop");
00079   ast_string_field_set(x, foo, NULL); // set to an empty string
00080   ast_string_field_ptr_set(x, &x->bar, "right way");
00081 
00082   ast_string_field_build(x, blah, "%d %s", zipcode, city);
00083   ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
00084 
00085   ast_string_field_build_va(x, bar, fmt, args1, args2)
00086   ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
00087   \endcode
00088 
00089   When the structure instance is no longer needed, the fields
00090   and their storage pool must be freed:
00091   
00092   \code
00093   ast_string_field_free_memory(x);
00094   ast_free(x);
00095   \endcode
00096 
00097   This completes the API description.
00098 */
00099 
00100 #ifndef _ASTERISK_STRINGFIELDS_H
00101 #define _ASTERISK_STRINGFIELDS_H
00102 
00103 #include "asterisk/inline_api.h"
00104 
00105 /*!
00106   \internal
00107   \brief An opaque type for managed string fields in structures
00108 
00109   Don't declare instances of this type directly; use the AST_STRING_FIELD()
00110   macro instead.
00111 
00112   In addition to the string itself, the amount of space allocated for the
00113   field is stored in the two bytes immediately preceding it.
00114 */
00115 typedef const char * ast_string_field;
00116 
00117 /*!
00118   \internal
00119   \brief A constant empty string used for fields that have no other value
00120 */
00121 extern const char *__ast_string_field_empty;
00122 
00123 /*!
00124   \internal
00125   \brief Structure used to hold a pool of space for string fields
00126 */
00127 struct ast_string_field_pool {
00128    struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
00129    size_t size;            /*!< the total size of the pool */
00130    size_t used;            /*!< the space used in the pool */
00131    size_t active;          /*!< the amount of space actively in use by fields */
00132    char base[0];           /*!< storage space for the fields */
00133 };
00134 
00135 /*!
00136   \internal
00137   \brief Structure used to manage the storage for a set of string fields.
00138 */
00139 struct ast_string_field_mgr {
00140    ast_string_field last_alloc;        /*!< the last field allocated */
00141    struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */
00142 #if defined(__AST_DEBUG_MALLOC)
00143    const char *owner_file;          /*!< filename of owner */
00144    const char *owner_func;          /*!< function name of owner */
00145    int owner_line;               /*!< line number of owner */
00146 #endif
00147 };
00148 
00149 /*!
00150   \internal
00151   \brief Attempt to 'grow' an already allocated field to a larger size
00152   \param mgr Pointer to the pool manager structure
00153   \param needed Amount of space needed for this field
00154   \param ptr Pointer to a field within the structure
00155   \return 0 on success, non-zero on failure
00156 
00157   This function will attempt to increase the amount of space allocated to
00158   an existing field to the amount requested; this is only possible if the
00159   field was the last field allocated from the current storage pool and
00160   the pool has enough space available. If so, the additional space will be
00161   allocated to this field and the field's address will not be changed.
00162 */
00163 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
00164             struct ast_string_field_pool **pool_head, size_t needed,
00165             const ast_string_field *ptr);
00166 
00167 /*!
00168   \internal
00169   \brief Allocate space for a field
00170   \param mgr Pointer to the pool manager structure
00171   \param needed Amount of space needed for this field
00172   \param fields Pointer to the first entry of the field array
00173   \return NULL on failure, an address for the field on success.
00174 
00175   This function will allocate the requested amount of space from
00176   the field pool. If the requested amount of space is not available,
00177   an additional pool will be allocated.
00178 */
00179 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
00180                   struct ast_string_field_pool **pool_head, size_t needed);
00181 
00182 /*!
00183   \internal
00184   \brief Set a field to a complex (built) value
00185   \param mgr Pointer to the pool manager structure
00186   \param pool_head Pointer to the current pool
00187   \param ptr Pointer to a field within the structure
00188   \param format printf-style format string
00189   \return nothing
00190 */
00191 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
00192               struct ast_string_field_pool **pool_head,
00193               ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
00194 
00195 /*!
00196   \internal
00197   \brief Set a field to a complex (built) value
00198   \param mgr Pointer to the pool manager structure
00199   \param pool_head Pointer to the current pool
00200   \param ptr Pointer to a field within the structure
00201   \param format printf-style format string
00202   \param args va_list of the args for the format_string
00203   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
00204   \return nothing
00205 */
00206 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
00207                  struct ast_string_field_pool **pool_head,
00208                  ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
00209 
00210 /*!
00211   \brief Declare a string field
00212   \param name The field name
00213 */
00214 #define AST_STRING_FIELD(name) const ast_string_field name
00215 
00216 /*!
00217   \brief Declare the fields needed in a structure
00218   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
00219   Internally, string fields are stored as a pointer to the head of the pool,
00220   followed by individual string fields, and then a struct ast_string_field_mgr
00221   which describes the space allocated.
00222   We split the two variables so they can be used as markers around the
00223   field_list, and this allows us to determine how many entries are in
00224   the field, and play with them.
00225   In particular, for writing to the fields, we rely on __field_mgr_pool to be
00226   a non-const pointer, so we know it has the same size as ast_string_field,
00227   and we can use it to locate the fields.
00228 */
00229 #define AST_DECLARE_STRING_FIELDS(field_list) \
00230    struct ast_string_field_pool *__field_mgr_pool; \
00231    field_list              \
00232    struct ast_string_field_mgr __field_mgr
00233 
00234 /*!
00235   \brief Initialize a field pool and fields
00236   \param x Pointer to a structure containing fields
00237   \param size Amount of storage to allocate.
00238    Use 0 to reset fields to the default value,
00239    and release all but the most recent pool.
00240    size<0 (used internally) means free all pools.
00241   \return 0 on success, non-zero on failure
00242 */
00243 #define ast_string_field_init(x, size) \
00244    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00245 
00246 /*! \brief free all memory - to be called before destroying the object */
00247 #define ast_string_field_free_memory(x)   \
00248    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00249 
00250 /*!
00251  * \internal
00252  * \brief internal version of ast_string_field_init
00253  */
00254 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
00255              int needed, const char *file, int lineno, const char *func);
00256 
00257 /*!
00258  * \brief Allocate a structure with embedded stringfields in a single allocation
00259  * \param n Number of structures to allocate (see ast_calloc)
00260  * \param type The type of structure to allocate
00261  * \param size The number of bytes of space (minimum) to allocate for stringfields to use
00262  *
00263  * This function will allocate memory for one or more structures that use stringfields, and
00264  * also allocate space for the stringfields and initialize the stringfield management
00265  * structure embedded in the outer structure.
00266  *
00267  * \since 1.8
00268  */
00269 #define ast_calloc_with_stringfields(n, type, size) \
00270    __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
00271                    size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00272 
00273 /*!
00274  * \internal
00275  * \brief internal version of ast_calloc_with_stringfields
00276  */
00277 void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
00278                          size_t field_mgr_pool_offset, size_t pool_size, const char *file,
00279                          int lineno, const char *func);
00280 
00281 /*!
00282   \internal
00283   \brief Release a field's allocation from a pool
00284   \param pool_head Pointer to the current pool
00285   \param ptr Field to be released
00286   \return nothing
00287 
00288   This function will search the pool list to find the pool that contains
00289   the allocation for the specified field, then remove the field's allocation
00290   from that pool's 'active' count. If the pool's active count reaches zero,
00291   and it is not the current pool, then it will be freed.
00292  */
00293 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
00294                    const ast_string_field ptr);
00295 
00296 /* the type of storage used to track how many bytes were allocated for a field */
00297 
00298 typedef uint16_t ast_string_field_allocation;
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 #define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - sizeof(ast_string_field_allocation)))
00305 
00306 /*!
00307   \brief Set a field to a simple string value
00308   \param x Pointer to a structure containing fields
00309   \param ptr Pointer to a field within the structure
00310   \param data String value to be copied into the field 
00311   \return nothing
00312 */
00313 #define ast_string_field_ptr_set(x, ptr, data) do {                           \
00314    const char *__d__ = (data);                                 \
00315    size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;                      \
00316    ast_string_field *__p__ = (ast_string_field *) (ptr);                      \
00317    if (__dlen__ == 1) {                                  \
00318       __ast_string_field_release_active((x)->__field_mgr_pool, *__p__);             \
00319       *__p__ = __ast_string_field_empty;                          \
00320    } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) ||                     \
00321          (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) ||   \
00322          (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) {  \
00323       if (*__p__ != (*ptr)) {                               \
00324          __ast_string_field_release_active((x)->__field_mgr_pool, (*ptr));          \
00325       }                                      \
00326       memcpy(* (void **) __p__, __d__, __dlen__);                       \
00327    }                                         \
00328    } while (0)
00329 
00330 /*!
00331   \brief Set a field to a simple string value
00332   \param x Pointer to a structure containing fields
00333   \param field Name of the field to set
00334   \param data String value to be copied into the field
00335   \return nothing
00336 */
00337 #define ast_string_field_set(x, field, data) do {     \
00338    ast_string_field_ptr_set(x, &(x)->field, data);    \
00339    } while (0)
00340 
00341 /*!
00342   \brief Set a field to a complex (built) value
00343   \param x Pointer to a structure containing fields
00344   \param ptr Pointer to a field within the structure
00345   \param fmt printf-style format string
00346   \param args Arguments for format string
00347   \return nothing
00348 */
00349 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
00350    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
00351 
00352 /*!
00353   \brief Set a field to a complex (built) value
00354   \param x Pointer to a structure containing fields
00355   \param field Name of the field to set
00356   \param fmt printf-style format string
00357   \param args Arguments for format string
00358   \return nothing
00359 */
00360 #define ast_string_field_build(x, field, fmt, args...) \
00361    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
00362 
00363 /*!
00364   \brief Set a field to a complex (built) value with prebuilt va_lists.
00365   \param x Pointer to a structure containing fields
00366   \param ptr Pointer to a field within the structure
00367   \param fmt printf-style format string
00368   \param args1 Arguments for format string in va_list format
00369   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
00370   \return nothing
00371 */
00372 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
00373    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2)
00374 
00375 /*!
00376   \brief Set a field to a complex (built) value
00377   \param x Pointer to a structure containing fields
00378   \param field Name of the field to set
00379   \param fmt printf-style format string
00380   \param args1 argument one
00381   \param args2 argument two
00382   \return nothing
00383 */
00384 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
00385    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2)
00386 
00387 #endif /* _ASTERISK_STRINGFIELDS_H */

Generated on Wed Apr 6 11:29:48 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7