Wed Oct 28 11:51:08 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 #if defined(__AST_DEBUG_MALLOC)
00142    const char *owner_file;          /*!< filename of owner */
00143    const char *owner_func;          /*!< function name of owner */
00144    int owner_line;               /*!< line number of owner */
00145 #endif
00146 };
00147 
00148 /*!
00149   \internal
00150   \brief Attempt to 'grow' an already allocated field to a larger size
00151   \param mgr Pointer to the pool manager structure
00152   \param needed Amount of space needed for this field
00153   \param ptr Pointer to a field within the structure
00154   \return 0 on success, non-zero on failure
00155 
00156   This function will attempt to increase the amount of space allocated to
00157   an existing field to the amount requested; this is only possible if the
00158   field was the last field allocated from the current storage pool and
00159   the pool has enough space available. If so, the additional space will be
00160   allocated to this field and the field's address will not be changed.
00161 */
00162 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
00163             const ast_string_field *ptr);
00164 
00165 /*!
00166   \internal
00167   \brief Allocate space for a field
00168   \param mgr Pointer to the pool manager structure
00169   \param needed Amount of space needed for this field
00170   \param fields Pointer to the first entry of the field array
00171   \return NULL on failure, an address for the field on success.
00172 
00173   This function will allocate the requested amount of space from
00174   the field pool. If the requested amount of space is not available,
00175   an additional pool will be allocated.
00176 */
00177 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
00178                   struct ast_string_field_pool **pool_head, size_t needed);
00179 
00180 /*!
00181   \internal
00182   \brief Set a field to a complex (built) value
00183   \param mgr Pointer to the pool manager structure
00184   \param fields Pointer to the first entry of the field array
00185   \param ptr Pointer to a field within the structure
00186   \param format printf-style format string
00187   \return nothing
00188 */
00189 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
00190               struct ast_string_field_pool **pool_head,
00191               ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
00192 
00193 /*!
00194   \internal
00195   \brief Set a field to a complex (built) value
00196   \param mgr Pointer to the pool manager structure
00197   \param fields Pointer to the first entry of the field array
00198   \param ptr Pointer to a field within the structure
00199   \param format printf-style format string
00200   \param args va_list of the args for the format_string
00201   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
00202   \return nothing
00203 */
00204 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
00205                  struct ast_string_field_pool **pool_head,
00206                  ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
00207 
00208 /*!
00209   \brief Declare a string field
00210   \param name The field name
00211 */
00212 #define AST_STRING_FIELD(name) const ast_string_field name
00213 
00214 /*!
00215   \brief Declare the fields needed in a structure
00216   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
00217   Internally, string fields are stored as a pointer to the head of the pool,
00218   followed by individual string fields, and then a struct ast_string_field_mgr
00219   which describes the space allocated.
00220   We split the two variables so they can be used as markers around the
00221   field_list, and this allows us to determine how many entries are in
00222   the field, and play with them.
00223   In particular, for writing to the fields, we rely on __field_mgr_pool to be
00224   a non-const pointer, so we know it has the same size as ast_string_field,
00225   and we can use it to locate the fields.
00226 */
00227 #define AST_DECLARE_STRING_FIELDS(field_list) \
00228    struct ast_string_field_pool *__field_mgr_pool; \
00229    field_list              \
00230    struct ast_string_field_mgr __field_mgr
00231 
00232 /*!
00233   \brief Initialize a field pool and fields
00234   \param x Pointer to a structure containing fields
00235   \param size Amount of storage to allocate.
00236    Use 0 to reset fields to the default value,
00237    and release all but the most recent pool.
00238    size<0 (used internally) means free all pools.
00239   \return 0 on success, non-zero on failure
00240 */
00241 #define ast_string_field_init(x, size) \
00242    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00243 
00244 /*! \brief free all memory - to be called before destroying the object */
00245 #define ast_string_field_free_memory(x)   \
00246    __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00247 
00248 /*!
00249  * \internal
00250  * \brief internal version of ast_string_field_init
00251  */
00252 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
00253              int needed, const char *file, int lineno, const char *func);
00254 
00255 /*!
00256   \brief Set a field to a simple string value
00257   \param x Pointer to a structure containing fields
00258   \param ptr Pointer to a field within the structure
00259   \param data String value to be copied into the field
00260   \return nothing
00261 */
00262 #define ast_string_field_ptr_set(x, ptr, data) do {      \
00263    const char *__d__ = (data);            \
00264    size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
00265    const char **__p__ = (const char **) (ptr);     \
00266    char *__q__; \
00267    if (__dlen__ == 1)               \
00268       *__p__ = __ast_string_field_empty;     \
00269    else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
00270       __q__ = (char *) *__p__; \
00271       memcpy(__q__, __d__, __dlen__);  \
00272    } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
00273       __q__ = (char *) *__p__; \
00274       memcpy(__q__, __d__, __dlen__);  \
00275    } \
00276    } while (0)
00277 
00278 /*!
00279   \brief Set a field to a simple string value
00280   \param x Pointer to a structure containing fields
00281   \param field Name of the field to set
00282   \param data String value to be copied into the field
00283   \return nothing
00284 */
00285 #define ast_string_field_set(x, field, data) do {     \
00286    ast_string_field_ptr_set(x, &(x)->field, data);    \
00287    } while (0)
00288 
00289 /*!
00290   \brief Set a field to a complex (built) value
00291   \param x Pointer to a structure containing fields
00292   \param ptr Pointer to a field within the structure
00293   \param fmt printf-style format string
00294   \param args Arguments for format string
00295   \return nothing
00296 */
00297 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
00298    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
00299 
00300 /*!
00301   \brief Set a field to a complex (built) value
00302   \param x Pointer to a structure containing fields
00303   \param field Name of the field to set
00304   \param fmt printf-style format string
00305   \param args Arguments for format string
00306   \return nothing
00307 */
00308 #define ast_string_field_build(x, field, fmt, args...) \
00309    __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
00310 
00311 /*!
00312   \brief Set a field to a complex (built) value with prebuilt va_lists.
00313   \param x Pointer to a structure containing fields
00314   \param ptr Pointer to a field within the structure
00315   \param fmt printf-style format string
00316   \param args1 Arguments for format string in va_list format
00317   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
00318   \return nothing
00319 */
00320 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
00321    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2)
00322 
00323 /*!
00324   \brief Set a field to a complex (built) value
00325   \param x Pointer to a structure containing fields
00326   \param field Name of the field to set
00327   \param fmt printf-style format string
00328   \param args1 argument one
00329   \param args2 argument two
00330   \return nothing
00331 */
00332 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
00333    __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2)
00334 
00335 #endif /* _ASTERISK_STRINGFIELDS_H */

Generated on Wed Oct 28 11:51:08 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6