Fri Jun 19 12:09:53 2009

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 (this feature is not used
00061   in this code, but comes from external requirements).
00062 
00063   ast_string_field_init(x, 0) will reset fields to the
00064   initial value while keeping the pool allocated.
00065   
00066   Reading the fields is much like using 'const char * const' fields in the
00067   structure: you cannot write to the field or to the memory it points to
00068   (XXX perhaps the latter is too much of a restriction since values
00069   are not shared).
00070 
00071   Writing to the fields must be done using the wrapper macros listed below;
00072   and assignments are always by value (i.e. strings are copied):
00073   * ast_string_field_set() stores a simple value;
00074   * ast_string_field_build() builds the string using a printf-style;
00075   * ast_string_field_build_va() is the varargs version of the above (for
00076     portability reasons it uses two vararg);
00077   * variants of these function allow passing a pointer to the field
00078     as an argument.
00079   \code
00080   ast_string_field_set(x, foo, "infinite loop");
00081   ast_string_field_set(x, foo, NULL); // set to an empty string
00082   ast_string_field_ptr_set(x, &x->bar, "right way");
00083 
00084   ast_string_field_build(x, blah, "%d %s", zipcode, city);
00085   ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
00086 
00087   ast_string_field_build_va(x, bar, fmt, args1, args2)
00088   ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
00089   \endcode
00090 
00091   When the structure instance is no longer needed, the fields
00092   and their storage pool must be freed:
00093   
00094   \code
00095   ast_string_field_free_memory(x);
00096   ast_free(x);
00097   \endcode
00098 
00099   This completes the API description.
00100 */
00101 
00102 #ifndef _ASTERISK_STRINGFIELDS_H
00103 #define _ASTERISK_STRINGFIELDS_H
00104 
00105 #include "asterisk/inline_api.h"
00106 
00107 /*!
00108   \internal
00109   \brief An opaque type for managed string fields in structures
00110 
00111   Don't declare instances of this type directly; use the AST_STRING_FIELD()
00112   macro instead.
00113 */
00114 typedef const char * ast_string_field;
00115 
00116 /*!
00117   \internal
00118   \brief A constant empty string used for fields that have no other value
00119 */
00120 extern const char __ast_string_field_empty[];
00121 
00122 /*!
00123   \internal
00124   \brief Structure used to hold a pool of space for string fields
00125 */
00126 struct ast_string_field_pool {
00127    struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
00128    char base[0];           /*!< storage space for the fields */
00129 };
00130 
00131 /*!
00132   \internal
00133   \brief Structure used to manage the storage for a set of string fields.
00134   Because of the way pools are managed, we can only allocate from the topmost
00135   pool, so the numbers here reflect just that.
00136 */
00137 struct ast_string_field_mgr {
00138    size_t size;            /*!< the total size of the current pool */
00139    size_t used;            /*!< the space used in the current pool */
00140    ast_string_field last_alloc;     /*!< the last field allocated */
00141 };
00142 
00143 /*!
00144   \internal
00145   \brief Attempt to 'grow' an already allocated field to a larger size
00146   \param mgr Pointer to the pool manager structure
00147   \param needed Amount of space needed for this field
00148   \param ptr Pointer to a field within the structure
00149   \return 0 on success, non-zero on failure
00150 
00151   This function will attempt to increase the amount of space allocated to
00152   an existing field to the amount requested; this is only possible if the
00153   field was the last field allocated from the current storage pool and
00154   the pool has enough space available. If so, the additional space will be
00155   allocated to this field and the field's address will not be changed.
00156 */
00157 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
00158             const ast_string_field *ptr);
00159 
00160 /*!
00161   \internal
00162   \brief Allocate space for a field
00163   \param mgr Pointer to the pool manager structure
00164   \param needed Amount of space needed for this field
00165   \param fields Pointer to the first entry of the field array
00166   \return NULL on failure, an address for the field on success.
00167 
00168   This function will allocate the requested amount of space from
00169   the field pool. If the requested amount of space is not available,
00170   an additional pool will be allocated.
00171 */
00172 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
00173                   struct ast_string_field_pool **pool_head, size_t needed);
00174 
00175 /*!
00176   \internal
00177   \brief Set a field to a complex (built) value
00178   \param mgr Pointer to the pool manager structure
00179   \param fields Pointer to the first entry of the field array
00180   \param ptr Pointer to a field within the structure
00181   \param format printf-style format string
00182   \return nothing
00183 */
00184 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
00185               struct ast_string_field_pool **pool_head,
00186               ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
00187 
00188 /*!
00189   \internal
00190   \brief Set a field to a complex (built) value
00191   \param mgr Pointer to the pool manager structure
00192   \param fields Pointer to the first entry of the field array
00193   \param ptr Pointer to a field within the structure
00194   \param format printf-style format string
00195   \param args va_list of the args for the format_string
00196   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
00197   \return nothing
00198 */
00199 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
00200                  struct ast_string_field_pool **pool_head,
00201                  ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
00202 
00203 /*!
00204   \brief Declare a string field
00205   \param name The field name
00206 */
00207 #define AST_STRING_FIELD(name) const ast_string_field name
00208 
00209 /*!
00210   \brief Declare the fields needed in a structure
00211   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
00212   Internally, string fields are stored as a pointer to the head of the pool,
00213   followed by individual string fields, and then a struct ast_string_field_mgr
00214   which describes the space allocated.
00215   We split the two variables so they can be used as markers around the
00216   field_list, and this allows us to determine how many entries are in
00217   the field, and play with them.
00218   In particular, for writing to the fields, we rely on __field_mgr_pool to be
00219   a non-const pointer, so we know it has the same size as ast_string_field,
00220   and we can use it to locate the fields.
00221 */
00222 #define AST_DECLARE_STRING_FIELDS(field_list) \
00223    struct ast_string_field_pool *__field_mgr_pool; \
00224    field_list              \
00225    struct ast_string_field_mgr __field_mgr
00226 
00227 /*!
00228   \brief Initialize a field pool and fields
00229   \param x Pointer to a structure containing fields
00230   \param size Amount of storage to allocate.
00231    Use 0 to reset fields to the default value,
00232    and release all but the most recent pool.
00233    size<0 (used internally) means free all pools.
00234   \return 0 on success, non-zero on failure
00235 */
00236 #define ast_string_field_init(x, size) \
00237    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size)
00238 
00239 /*! \brief free all memory - to be called before destroying the object */
00240 #define ast_string_field_free_memory(x)   \
00241    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1)
00242 
00243 /*! \internal \brief internal version of ast_string_field_init */
00244 int __ast_string_field_init(struct ast_string_field_mgr *mgr,
00245    struct ast_string_field_pool **pool_head, int needed);
00246 
00247 /*!
00248   \brief Set a field to a simple string value
00249   \param x Pointer to a structure containing fields
00250   \param ptr Pointer to a field within the structure
00251   \param data String value to be copied into the field
00252   \return nothing
00253 */
00254 #define ast_string_field_ptr_set(x, ptr, data) do {      \
00255    const char *__d__ = (data);            \
00256    size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
00257    const char **__p__ = (const char **) (ptr);     \
00258    char *__q__; \
00259    if (__dlen__ == 1)               \
00260       *__p__ = __ast_string_field_empty;     \
00261    else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
00262       __q__ = (char *) *__p__; \
00263       memcpy(__q__, __d__, __dlen__);  \
00264    } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
00265       __q__ = (char *) *__p__; \
00266       memcpy(__q__, __d__, __dlen__);  \
00267    } \
00268    } while (0)
00269 
00270 /*!
00271   \brief Set a field to a simple string value
00272   \param x Pointer to a structure containing fields
00273   \param field Name of the field to set
00274   \param data String value to be copied into the field
00275   \return nothing
00276 */
00277 #define ast_string_field_set(x, field, data) do {     \
00278    ast_string_field_ptr_set(x, &(x)->field, data);    \
00279    } while (0)
00280 
00281 /*!
00282   \brief Set a field to a complex (built) value
00283   \param x Pointer to a structure containing fields
00284   \param ptr Pointer to a field within the structure
00285   \param fmt printf-style format string
00286   \param args Arguments for format string
00287   \return nothing
00288 */
00289 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
00290    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
00291 
00292 /*!
00293   \brief Set a field to a complex (built) value
00294   \param x Pointer to a structure containing fields
00295   \param field Name of the field to set
00296   \param fmt printf-style format string
00297   \param args Arguments for format string
00298   \return nothing
00299 */
00300 #define ast_string_field_build(x, field, fmt, args...) \
00301    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
00302 
00303 /*!
00304   \brief Set a field to a complex (built) value with prebuilt va_lists.
00305   \param x Pointer to a structure containing fields
00306   \param ptr Pointer to a field within the structure
00307   \param fmt printf-style format string
00308   \param args1 Arguments for format string in va_list format
00309   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
00310   \return nothing
00311 */
00312 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
00313    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2)
00314 
00315 /*!
00316   \brief Set a field to a complex (built) value
00317   \param x Pointer to a structure containing fields
00318   \param field Name of the field to set
00319   \param fmt printf-style format string
00320   \param args1 argument one
00321   \param args2 argument two
00322   \return nothing
00323 */
00324 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
00325    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2)
00326 
00327 #endif /* _ASTERISK_STRINGFIELDS_H */

Generated on Fri Jun 19 12:09:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7