Sat Aug 6 00:39:32 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(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, ...) __attribute__((format(printf, 5, 6)));
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)  __attribute__((format(printf, 5, 0)));
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     char *__data__ = (char*) (data); \
00239     size_t __dlen__ = strlen(__data__) + 1; \
00240     if ( __dlen__ == 1 ) {\
00241       (x)->__begin_field[index] = __ast_string_field_empty; \
00242     } else { \
00243       if ((__zz__[0] != 0) && (__dlen__ <= (strlen(__zz__) + 1))) { \
00244         memcpy(__zz__, __data__, __dlen__); \
00245       } else { \
00246         if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) { \
00247           char *__yy__ = (char *) (x)->__begin_field[index]; \
00248           memcpy(__yy__, __data__, __dlen__); \
00249         } \
00250       } \
00251      } \
00252    } while (0)
00253 
00254 #define ast_string_field_index_logset(x, index, data, logstr) do { \
00255     char *__zz__ = (char*) (x)->__begin_field[index]; \
00256     char *__data__ = (char*) (data); \
00257     size_t __dlen__ = strlen(__data__) + 1; \
00258     if ( __dlen__ == 1 ) {\
00259       (x)->__begin_field[index] = __ast_string_field_empty; \
00260     } else { \
00261       if ((__zz__[0] != 0) && (__dlen__ <= strlen(__zz__) + 1)) { \
00262         ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, __data__); \
00263         memcpy(__zz__, __data__, __dlen__); \
00264       } else { \
00265         if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) \
00266           ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, __data__, __zz__); \
00267           memcpy((char*) (x)->__begin_field[index], __data__, __dlen__); \
00268       } \
00269      } \
00270    } while (0)
00271 
00272 /*!
00273   \brief Set a field to a simple string value
00274   \param x Pointer to a structure containing fields
00275   \param field Name of the field to set
00276   \param data String value to be copied into the field
00277   \return nothing
00278 */
00279 #define ast_string_field_set(x, field, data) \
00280    ast_string_field_index_set(x, ast_string_field_index(x, field), data)
00281 
00282 #define ast_string_field_logset(x, field, data, logstr) \
00283    ast_string_field_index_logset(x, ast_string_field_index(x, field), data, logstr)
00284 
00285 /*!
00286   \brief Set a field to a complex (built) value
00287   \param x Pointer to a structure containing fields
00288   \param index Index position of the field within the structure
00289   \param fmt printf-style format string
00290   \param args Arguments for format string
00291   \return nothing
00292 */
00293 #define ast_string_field_index_build(x, index, fmt, args...) \
00294    __ast_string_field_index_build(&(x)->__field_mgr, &(x)->__begin_field[0], ast_string_field_count(x), index, fmt, args)
00295 
00296 /*!
00297   \brief Set a field to a complex (built) value with prebuilt va_lists.
00298   \param x Pointer to a structure containing fields
00299   \param index Index position of the field within the structure
00300   \param fmt printf-style format string
00301   \param args1 Arguments for format string in va_list format
00302   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
00303   \return nothing
00304 */
00305 #define ast_string_field_index_build_va(x, index, fmt, args1, args2) \
00306    __ast_string_field_index_build_va(&(x)->__field_mgr, &(x)->__begin_field[0], ast_string_field_count(x), index, fmt, args1, args2)
00307 
00308 /*!
00309   \brief Set a field to a complex (built) value
00310   \param x Pointer to a structure containing fields
00311   \param field Name of the field to set
00312   \param fmt printf-style format string
00313   \param args Arguments for format string
00314   \return nothing
00315 */
00316 #define ast_string_field_build(x, field, fmt, args...) \
00317    ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
00318 
00319 /*!
00320   \brief Set a field to a complex (built) value
00321   \param x Pointer to a structure containing fields
00322   \param field Name of the field to set
00323   \param fmt printf-style format string
00324   \param argslist a va_list of the args
00325   \return nothing
00326 */
00327 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
00328    ast_string_field_index_build_va(x, ast_string_field_index(x, field), fmt, args1, args2)
00329 
00330 /*!
00331   \brief Free a field's value.
00332   \param x Pointer to a structure containing fields
00333   \param index Index position of the field within the structure
00334   \return nothing
00335 
00336   \note Because of the storage pool used, the memory
00337   occupied by the field's value is \b not recovered; the field
00338   pointer is just changed to point to an empty string.
00339 */
00340 #define ast_string_field_index_free(x, index) do { \
00341    (x)->__begin_field[index] = __ast_string_field_empty; \
00342    } while(0)
00343 
00344 /*!
00345   \brief Free a field's value.
00346   \param x Pointer to a structure containing fields
00347   \param field Name of the field to free
00348   \return nothing
00349 
00350   \note Because of the storage pool used, the memory
00351   occupied by the field's value is \b not recovered; the field
00352   pointer is just changed to point to an empty string.
00353 */
00354 #define ast_string_field_free(x, field) \
00355    ast_string_field_index_free(x, ast_string_field_index(x, field))
00356 
00357 /*!
00358   \brief Free the stringfield storage pools attached to a structure
00359   \param x Pointer to a structure containing fields
00360   \return nothing
00361 
00362   After calling this macro, fields can no longer be accessed in
00363   structure; it should only be called immediately before freeing
00364   the structure itself.
00365 */
00366 #define ast_string_field_free_memory(x) do { \
00367    struct ast_string_field_pool *this, *prev; \
00368    for (this = (x)->__field_mgr.pool; this; this = prev) { \
00369       prev = this->prev; \
00370       free(this); \
00371    } \
00372    } while(0)
00373 
00374 /*!
00375   \brief Free the stringfields in a structure
00376   \param x Pointer to a structure containing fields
00377   \return nothing
00378 
00379   After calling this macro, the most recently allocated pool
00380   attached to the structure will be available for use by
00381   stringfields again.
00382 */
00383 #define ast_string_field_reset_all(x) do { \
00384    int index; \
00385    for (index = 0; index < ast_string_field_count(x); index++) \
00386       ast_string_field_index_free(x, index); \
00387    (x)->__field_mgr.used = 0; \
00388    (x)->__field_mgr.space = (x)->__field_mgr.size; \
00389    } while(0)
00390 
00391 #endif /* _ASTERISK_STRINGFIELDS_H */

Generated on Sat Aug 6 00:39:32 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7