Mon Jul 14 17:25:02 2008

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(name);
00035         AST_STRING_FIELD(address);
00036         AST_STRING_FIELD(password);
00037      );
00038      long x2;
00039   };
00040   \endcode
00041   
00042   When an instance of this structure is allocated, the fields
00043   (and the pool of storage for them) must be initialized:
00044   
00045   \code
00046   struct sample_fields *sample;
00047   
00048   sample = calloc(1, sizeof(*sample));
00049   if (sample) {
00050      if (ast_string_field_init(sample, 256)) {
00051         free(sample);
00052         sample = NULL;
00053      }
00054   }
00055   
00056   if (!sample) {
00057   ...
00058   }
00059   \endcode
00060   
00061   Fields will default to pointing to an empty string, and will
00062   revert to that when ast_string_field_free() is called. This means
00063   that a string field will \b never contain NULL.
00064   
00065   Using the fields is much like using regular 'char *' fields
00066   in the structure, except that writing into them must be done
00067   using wrapper macros defined in this file.
00068   
00069   Storing simple values into fields can be done using ast_string_field_set();
00070   more complex values (using printf-style format strings) can be stored
00071   using ast_string_field_build().
00072   
00073   When the structure instance is no longer needed, the fields
00074   and their storage pool must be freed:
00075   
00076   \code
00077   ast_string_field_free_memory(sample);
00078   free(sample);
00079   \endcode
00080 */
00081 
00082 #ifndef _ASTERISK_STRINGFIELDS_H
00083 #define _ASTERISK_STRINGFIELDS_H
00084 
00085 #include <string.h>
00086 #include <stdarg.h>
00087 #include <stddef.h>
00088 
00089 #include "asterisk/inline_api.h"
00090 #include "asterisk/compiler.h"
00091 #include "asterisk/compat.h"
00092 
00093 /*!
00094   \internal
00095   \brief An opaque type for managed string fields in structures
00096 
00097   Don't declare instances of this type directly; use the AST_STRING_FIELD()
00098   macro instead.
00099 */
00100 typedef const char * ast_string_field;
00101 
00102 /*!
00103   \internal
00104   \brief A constant empty string used for fields that have no other value
00105 */
00106 extern const char __ast_string_field_empty[];
00107 
00108 /*!
00109   \internal
00110   \brief Structure used to hold a pool of space for string fields
00111 */
00112 struct ast_string_field_pool {
00113    struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
00114    char base[0];           /*!< storage space for the fields */
00115 };
00116 
00117 /*!
00118   \internal
00119   \brief Structure used to manage the storage for a set of string fields
00120 */
00121 struct ast_string_field_mgr {
00122    struct ast_string_field_pool *pool; /*!< the address of the pool's structure */
00123    size_t size;            /*!< the total size of the current pool */
00124    size_t space;           /*!< the space available in the current pool */
00125    size_t used;            /*!< the space used in the current pool */
00126 };
00127 
00128 /*!
00129   \internal
00130   \brief Initialize a field pool manager and fields
00131   \param mgr Pointer to the pool manager structure
00132   \param size Amount of storage to allocate
00133   \param fields Pointer to the first entry of the field array
00134   \param num_fields Number of fields in the array
00135   \return 0 on success, non-zero on failure
00136 */
00137 int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
00138              ast_string_field *fields, int num_fields);
00139 
00140 /*!
00141   \internal
00142   \brief Allocate space for a field
00143   \param mgr Pointer to the pool manager structure
00144   \param needed Amount of space needed for this field
00145   \param fields Pointer to the first entry of the field array
00146   \param num_fields Number of fields in the array
00147   \return NULL on failure, an address for the field on success
00148 
00149   This function will allocate the requested amount of space from
00150   the field pool. If the requested amount of space is not available,
00151   an additional pool will be allocated.
00152 */
00153 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
00154                   ast_string_field *fields, int num_fields);
00155 
00156 /*!
00157   \internal
00158   \brief Set a field to a complex (built) value
00159   \param mgr Pointer to the pool manager structure
00160   \param fields Pointer to the first entry of the field array
00161   \param num_fields Number of fields in the array
00162   \param index Index position of the field within the structure
00163   \param format printf-style format string
00164   \return nothing
00165 */
00166 void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
00167                 ast_string_field *fields, int num_fields,
00168                 int index, const char *format, ...);
00169 
00170 /*!
00171   \internal
00172   \brief Set a field to a complex (built) value
00173   \param mgr Pointer to the pool manager structure
00174   \param fields Pointer to the first entry of the field array
00175   \param num_fields Number of fields in the array
00176   \param index Index position of the field within the structure
00177   \param format printf-style format string
00178   \param args va_list of the args for the format_string
00179   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
00180   \return nothing
00181 */
00182 void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
00183                 ast_string_field *fields, int num_fields,
00184                 int index, const char *format, va_list a1, va_list a2);
00185 
00186 /*!
00187   \brief Declare a string field
00188   \param name The field name
00189 */
00190 #define AST_STRING_FIELD(name) const ast_string_field name
00191 
00192 /*!
00193   \brief Declare the fields needed in a structure
00194   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
00195 */
00196 #define AST_DECLARE_STRING_FIELDS(field_list) \
00197    ast_string_field __begin_field[0]; \
00198    field_list \
00199    ast_string_field __end_field[0]; \
00200    struct ast_string_field_mgr __field_mgr
00201 
00202 /*!
00203   \brief Get the number of string fields in a structure
00204   \param x Pointer to a structure containing fields
00205   \return the number of fields in the structure's definition
00206 */
00207 #define ast_string_field_count(x) \
00208    (offsetof(typeof(*(x)), __end_field) - offsetof(typeof(*(x)), __begin_field)) / sizeof(ast_string_field)
00209 
00210 /*!
00211   \brief Get the index of a field in a structure
00212   \param x Pointer to a structure containing fields
00213   \param field Name of the field to locate
00214   \return the position (index) of the field within the structure's
00215   array of fields
00216 */
00217 #define ast_string_field_index(x, field) \
00218    (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
00219 
00220 /*!
00221   \brief Initialize a field pool and fields
00222   \param x Pointer to a structure containing fields
00223   \param size Amount of storage to allocate
00224   \return 0 on success, non-zero on failure
00225 */
00226 #define ast_string_field_init(x, size) \
00227    __ast_string_field_init(&(x)->__field_mgr, size, &(x)->__begin_field[0], ast_string_field_count(x))
00228 
00229 /*!
00230   \brief Set a field to a simple string value
00231   \param x Pointer to a structure containing fields
00232   \param index Index position of the field within the structure
00233   \param data String value to be copied into the field
00234   \return nothing
00235 */
00236 #define ast_string_field_index_set(x, index, data) do { \
00237     char *__zz__ = (char*)(x)->__begin_field[index]; \
00238     size_t __dlen__ = strlen(data); \
00239     if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
00240     } else { \
00241      if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
00242       strcpy(__zz__, data); \
00243      } else { \
00244        if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
00245           strcpy((char*)(x)->__begin_field[index], data); \
00246     } \
00247    } \
00248    } while (0)
00249 
00250 #ifdef FOR_TEST
00251 #define ast_string_field_index_logset(x, index, data, logstr) do { \
00252     char *__zz__ = (char*)(x)->__begin_field[index]; \
00253     size_t __dlen__ = strlen(data); \
00254     if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
00255     } else { \
00256      if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
00257        ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
00258       strcpy(__zz__, data); \
00259      } else { \
00260        ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
00261        if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
00262           strcpy((char*)(x)->__begin_field[index], data); \
00263     } \
00264    } \
00265    } while (0)
00266 #endif
00267 
00268 /*!
00269   \brief Set a field to a simple string value
00270   \param x Pointer to a structure containing fields
00271   \param field Name of the field to set
00272   \param data String value to be copied into the field
00273   \return nothing
00274 */
00275 #define ast_string_field_set(x, field, data) \
00276    ast_string_field_index_set(x, ast_string_field_index(x, field), data)
00277 
00278 #ifdef FOR_TEST
00279 #define ast_string_field_logset(x, field, data, logstr) \
00280    ast_string_field_index_logset(x, ast_string_field_index(x, field), data, logstr)
00281 #endif
00282 
00283 /*!
00284   \brief Set a field to a complex (built) value
00285   \param x Pointer to a structure containing fields
00286   \param index Index position of the field within the structure
00287   \param fmt printf-style format string
00288   \param args Arguments for format string
00289   \return nothing
00290 */
00291 #define ast_string_field_index_build(x, index, fmt, args...) \
00292    __ast_string_field_index_build(&(x)->__field_mgr, &(x)->__begin_field[0], ast_string_field_count(x), index, fmt, args)
00293 
00294 /*!
00295   \brief Set a field to a complex (built) value with prebuilt va_lists.
00296   \param x Pointer to a structure containing fields
00297   \param index Index position of the field within the structure
00298   \param fmt printf-style format string
00299   \param args1 Arguments for format string in va_list format
00300   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
00301   \return nothing
00302 */
00303 #define ast_string_field_index_build_va(x, index, fmt, args1, args2) \
00304    __ast_string_field_index_build_va(&(x)->__field_mgr, &(x)->__begin_field[0], ast_string_field_count(x), index, fmt, args1, args2)
00305 
00306 /*!
00307   \brief Set a field to a complex (built) value
00308   \param x Pointer to a structure containing fields
00309   \param field Name of the field to set
00310   \param fmt printf-style format string
00311   \param args Arguments for format string
00312   \return nothing
00313 */
00314 #define ast_string_field_build(x, field, fmt, args...) \
00315    ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
00316 
00317 /*!
00318   \brief Set a field to a complex (built) value
00319   \param x Pointer to a structure containing fields
00320   \param field Name of the field to set
00321   \param fmt printf-style format string
00322   \param argslist a va_list of the args
00323   \return nothing
00324 */
00325 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
00326    ast_string_field_index_build_va(x, ast_string_field_index(x, field), fmt, args1, args2)
00327 
00328 /*!
00329   \brief Free a field's value.
00330   \param x Pointer to a structure containing fields
00331   \param index Index position of the field within the structure
00332   \return nothing
00333 
00334   \note Because of the storage pool used, the memory
00335   occupied by the field's value is \b not recovered; the field
00336   pointer is just changed to point to an empty string.
00337 */
00338 #define ast_string_field_index_free(x, index) do { \
00339    (x)->__begin_field[index] = __ast_string_field_empty; \
00340    } while(0)
00341 
00342 /*!
00343   \brief Free a field's value.
00344   \param x Pointer to a structure containing fields
00345   \param field Name of the field to free
00346   \return nothing
00347 
00348   \note Because of the storage pool used, the memory
00349   occupied by the field's value is \b not recovered; the field
00350   pointer is just changed to point to an empty string.
00351 */
00352 #define ast_string_field_free(x, field) \
00353    ast_string_field_index_free(x, ast_string_field_index(x, field))
00354 
00355 /*!
00356   \brief Free the stringfield storage pools attached to a structure
00357   \param x Pointer to a structure containing fields
00358   \return nothing
00359 
00360   After calling this macro, fields can no longer be accessed in
00361   structure; it should only be called immediately before freeing
00362   the structure itself.
00363 */
00364 #define ast_string_field_free_memory(x) do { \
00365    struct ast_string_field_pool *this, *prev; \
00366    for (this = (x)->__field_mgr.pool; this; this = prev) { \
00367       prev = this->prev; \
00368       free(this); \
00369    } \
00370    } while(0)
00371 
00372 /*!
00373   \brief Free the stringfields in a structure
00374   \param x Pointer to a structure containing fields
00375   \return nothing
00376 
00377   After calling this macro, the most recently allocated pool
00378   attached to the structure will be available for use by
00379   stringfields again.
00380 */
00381 #define ast_string_field_reset_all(x) do { \
00382    int index; \
00383    for (index = 0; index < ast_string_field_count(x); index++) \
00384       ast_string_field_index_free(x, index); \
00385    (x)->__field_mgr.used = 0; \
00386    (x)->__field_mgr.space = (x)->__field_mgr.size; \
00387    } while(0)
00388 
00389 #endif /* _ASTERISK_STRINGFIELDS_H */

Generated on Mon Jul 14 17:25:02 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1