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 */