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. 00061 00062 ast_string_field_init(x, 0) will reset fields to the 00063 initial value while keeping the pool allocated. 00064 00065 Reading the fields is much like using 'const char * const' fields in the 00066 structure: you cannot write to the field or to the memory it points to. 00067 00068 Writing to the fields must be done using the wrapper macros listed below; 00069 and assignments are always by value (i.e. strings are copied): 00070 * ast_string_field_set() stores a simple value; 00071 * ast_string_field_build() builds the string using a printf-style format; 00072 * ast_string_field_build_va() is the varargs version of the above (for 00073 portability reasons it uses two vararg arguments); 00074 * variants of these function allow passing a pointer to the field 00075 as an argument. 00076 00077 \code 00078 ast_string_field_set(x, foo, "infinite loop"); 00079 ast_string_field_set(x, foo, NULL); // set to an empty string 00080 ast_string_field_ptr_set(x, &x->bar, "right way"); 00081 00082 ast_string_field_build(x, blah, "%d %s", zipcode, city); 00083 ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city); 00084 00085 ast_string_field_build_va(x, bar, fmt, args1, args2) 00086 ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2) 00087 \endcode 00088 00089 When the structure instance is no longer needed, the fields 00090 and their storage pool must be freed: 00091 00092 \code 00093 ast_string_field_free_memory(x); 00094 ast_free(x); 00095 \endcode 00096 00097 This completes the API description. 00098 */ 00099 00100 #ifndef _ASTERISK_STRINGFIELDS_H 00101 #define _ASTERISK_STRINGFIELDS_H 00102 00103 #include "asterisk/inline_api.h" 00104 00105 /*! 00106 \internal 00107 \brief An opaque type for managed string fields in structures 00108 00109 Don't declare instances of this type directly; use the AST_STRING_FIELD() 00110 macro instead. 00111 00112 In addition to the string itself, the amount of space allocated for the 00113 field is stored in the two bytes immediately preceding it. 00114 */ 00115 typedef const char * ast_string_field; 00116 00117 /* the type of storage used to track how many bytes were allocated for a field */ 00118 00119 typedef uint16_t ast_string_field_allocation; 00120 00121 /*! 00122 \internal 00123 \brief A constant empty string used for fields that have no other value 00124 */ 00125 extern const char *__ast_string_field_empty; 00126 00127 /*! 00128 \internal 00129 \brief Structure used to hold a pool of space for string fields 00130 \note base is aligned so base+used can stay aligned by incrementing used with 00131 aligned numbers only 00132 */ 00133 struct ast_string_field_pool { 00134 struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */ 00135 size_t size; /*!< the total size of the pool */ 00136 size_t used; /*!< the space used in the pool */ 00137 size_t active; /*!< the amount of space actively in use by fields */ 00138 char base[0] __attribute__((aligned(__alignof__(ast_string_field_allocation)))); /*!< storage space for the fields */ 00139 }; 00140 00141 /*! 00142 \internal 00143 \brief Structure used to manage the storage for a set of string fields. 00144 */ 00145 struct ast_string_field_mgr { 00146 ast_string_field last_alloc; /*!< the last field allocated */ 00147 struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */ 00148 #if defined(__AST_DEBUG_MALLOC) 00149 const char *owner_file; /*!< filename of owner */ 00150 const char *owner_func; /*!< function name of owner */ 00151 int owner_line; /*!< line number of owner */ 00152 #endif 00153 }; 00154 00155 /*! 00156 \internal 00157 \brief Attempt to 'grow' an already allocated field to a larger size 00158 \param mgr Pointer to the pool manager structure 00159 \param needed Amount of space needed for this field 00160 \param ptr Pointer to a field within the structure 00161 \return 0 on success, non-zero on failure 00162 00163 This function will attempt to increase the amount of space allocated to 00164 an existing field to the amount requested; this is only possible if the 00165 field was the last field allocated from the current storage pool and 00166 the pool has enough space available. If so, the additional space will be 00167 allocated to this field and the field's address will not be changed. 00168 */ 00169 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, 00170 struct ast_string_field_pool **pool_head, size_t needed, 00171 const ast_string_field *ptr); 00172 00173 /*! 00174 \internal 00175 \brief Allocate space for a field 00176 \param mgr Pointer to the pool manager structure 00177 \param needed Amount of space needed for this field 00178 \param fields Pointer to the first entry of the field array 00179 \return NULL on failure, an address for the field on success. 00180 00181 This function will allocate the requested amount of space from 00182 the field pool. If the requested amount of space is not available, 00183 an additional pool will be allocated. 00184 */ 00185 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, 00186 struct ast_string_field_pool **pool_head, size_t needed); 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 pool_head Pointer to the current pool 00193 \param ptr Pointer to a field within the structure 00194 \param format printf-style format string 00195 \return nothing 00196 */ 00197 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr, 00198 struct ast_string_field_pool **pool_head, 00199 ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5))); 00200 00201 /*! 00202 \internal 00203 \brief Set a field to a complex (built) value 00204 \param mgr Pointer to the pool manager structure 00205 \param pool_head Pointer to the current pool 00206 \param ptr Pointer to a field within the structure 00207 \param format printf-style format string 00208 \param args va_list of the args for the format_string 00209 \param args_again a copy of the first va_list for the sake of bsd not having a copy routine 00210 \return nothing 00211 */ 00212 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr, 00213 struct ast_string_field_pool **pool_head, 00214 ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0))); 00215 00216 /*! 00217 \brief Declare a string field 00218 \param name The field name 00219 */ 00220 #define AST_STRING_FIELD(name) const ast_string_field name 00221 00222 /*! 00223 \brief Declare the fields needed in a structure 00224 \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one. 00225 Internally, string fields are stored as a pointer to the head of the pool, 00226 followed by individual string fields, and then a struct ast_string_field_mgr 00227 which describes the space allocated. 00228 We split the two variables so they can be used as markers around the 00229 field_list, and this allows us to determine how many entries are in 00230 the field, and play with them. 00231 In particular, for writing to the fields, we rely on __field_mgr_pool to be 00232 a non-const pointer, so we know it has the same size as ast_string_field, 00233 and we can use it to locate the fields. 00234 */ 00235 #define AST_DECLARE_STRING_FIELDS(field_list) \ 00236 struct ast_string_field_pool *__field_mgr_pool; \ 00237 field_list \ 00238 struct ast_string_field_mgr __field_mgr 00239 00240 /*! 00241 \brief Initialize a field pool and fields 00242 \param x Pointer to a structure containing fields 00243 \param size Amount of storage to allocate. 00244 Use 0 to reset fields to the default value, 00245 and release all but the most recent pool. 00246 size<0 (used internally) means free all pools. 00247 \return 0 on success, non-zero on failure 00248 */ 00249 #define ast_string_field_init(x, size) \ 00250 __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__) 00251 00252 /*! \brief free all memory - to be called before destroying the object */ 00253 #define ast_string_field_free_memory(x) \ 00254 __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__) 00255 00256 /*! 00257 * \internal 00258 * \brief internal version of ast_string_field_init 00259 */ 00260 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, 00261 int needed, const char *file, int lineno, const char *func); 00262 00263 /*! 00264 * \brief Allocate a structure with embedded stringfields in a single allocation 00265 * \param n Number of structures to allocate (see ast_calloc) 00266 * \param type The type of structure to allocate 00267 * \param size The number of bytes of space (minimum) to allocate for stringfields to use 00268 * 00269 * This function will allocate memory for one or more structures that use stringfields, and 00270 * also allocate space for the stringfields and initialize the stringfield management 00271 * structure embedded in the outer structure. 00272 * 00273 * \since 1.8 00274 */ 00275 #define ast_calloc_with_stringfields(n, type, size) \ 00276 __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \ 00277 size, __FILE__, __LINE__, __PRETTY_FUNCTION__) 00278 00279 /*! 00280 * \internal 00281 * \brief internal version of ast_calloc_with_stringfields 00282 */ 00283 void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset, 00284 size_t field_mgr_pool_offset, size_t pool_size, const char *file, 00285 int lineno, const char *func); 00286 00287 /*! 00288 \internal 00289 \brief Release a field's allocation from a pool 00290 \param pool_head Pointer to the current pool 00291 \param ptr Field to be released 00292 \return nothing 00293 00294 This function will search the pool list to find the pool that contains 00295 the allocation for the specified field, then remove the field's allocation 00296 from that pool's 'active' count. If the pool's active count reaches zero, 00297 and it is not the current pool, then it will be freed. 00298 */ 00299 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head, 00300 const ast_string_field ptr); 00301 00302 /*! 00303 \brief Macro to provide access to the allocation field that lives immediately in front of a string field 00304 \param x Pointer to the string field 00305 00306 Note that x must be a pointer to a byte-sized type -- normally (char *) -- or this calculation 00307 would break horribly 00308 */ 00309 #define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - __alignof__(ast_string_field_allocation))) 00310 00311 /*! 00312 \brief Set a field to a simple string value 00313 \param x Pointer to a structure containing fields 00314 \param ptr Pointer to a field within the structure 00315 \param data String value to be copied into the field 00316 \return nothing 00317 */ 00318 #define ast_string_field_ptr_set(x, ptr, data) do { \ 00319 const char *__d__ = (data); \ 00320 size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \ 00321 ast_string_field *__p__ = (ast_string_field *) (ptr); \ 00322 ast_string_field target = *__p__; \ 00323 if (__dlen__ == 1) { \ 00324 __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \ 00325 *__p__ = __ast_string_field_empty; \ 00326 } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) || \ 00327 (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) || \ 00328 (target = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \ 00329 if (target != *__p__) { \ 00330 __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \ 00331 *__p__ = target; \ 00332 } \ 00333 memcpy(* (void **) __p__, __d__, __dlen__); \ 00334 } \ 00335 } while (0) 00336 00337 /*! 00338 \brief Set a field to a simple string value 00339 \param x Pointer to a structure containing fields 00340 \param field Name of the field to set 00341 \param data String value to be copied into the field 00342 \return nothing 00343 */ 00344 #define ast_string_field_set(x, field, data) do { \ 00345 ast_string_field_ptr_set(x, &(x)->field, data); \ 00346 } while (0) 00347 00348 /*! 00349 \brief Set a field to a complex (built) value 00350 \param x Pointer to a structure containing fields 00351 \param ptr Pointer to a field within the structure 00352 \param fmt printf-style format string 00353 \param args Arguments for format string 00354 \return nothing 00355 */ 00356 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \ 00357 __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args) 00358 00359 /*! 00360 \brief Set a field to a complex (built) value 00361 \param x Pointer to a structure containing fields 00362 \param field Name of the field to set 00363 \param fmt printf-style format string 00364 \param args Arguments for format string 00365 \return nothing 00366 */ 00367 #define ast_string_field_build(x, field, fmt, args...) \ 00368 __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args) 00369 00370 /*! 00371 \brief Set a field to a complex (built) value with prebuilt va_lists. 00372 \param x Pointer to a structure containing fields 00373 \param ptr Pointer to a field within the structure 00374 \param fmt printf-style format string 00375 \param args1 Arguments for format string in va_list format 00376 \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation 00377 \return nothing 00378 */ 00379 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \ 00380 __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2) 00381 00382 /*! 00383 \brief Set a field to a complex (built) value 00384 \param x Pointer to a structure containing fields 00385 \param field Name of the field to set 00386 \param fmt printf-style format string 00387 \param args1 argument one 00388 \param args2 argument two 00389 \return nothing 00390 */ 00391 #define ast_string_field_build_va(x, field, fmt, args1, args2) \ 00392 __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2) 00393 00394 #endif /* _ASTERISK_STRINGFIELDS_H */