Add a more efficient way of allocating structures that use stringfields
[asterisk/asterisk.git] / include / asterisk / stringfields.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006, Digium, Inc.
5  *
6  * Kevin P. Fleming <kpfleming@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20   \brief String fields in structures
21
22   This file contains objects and macros used to manage string
23   fields in structures without requiring them to be allocated
24   as fixed-size buffers or requiring individual allocations for
25   for each field.
26
27   Using this functionality is quite simple. An example structure
28   with three fields is defined like this:
29   
30   \code
31   struct sample_fields {
32           int x1;
33           AST_DECLARE_STRING_FIELDS(
34                   AST_STRING_FIELD(foo);
35                   AST_STRING_FIELD(bar);
36                   AST_STRING_FIELD(blah);
37           );
38           long x2;
39   };
40   \endcode
41   
42   When an instance of this structure is allocated (either statically or
43   dynamically), the fields and the pool of storage for them must be
44   initialized:
45   
46   \code
47   struct sample_fields *x;
48   
49   x = ast_calloc(1, sizeof(*x));
50   if (x == NULL || ast_string_field_init(x, 252)) {
51         if (x)
52                 ast_free(x);
53         x = NULL;
54         ... handle error
55   }
56   \endcode
57
58   Fields will default to pointing to an empty string, and will revert to
59   that when ast_string_field_set() is called with a NULL argument.
60   A string field will \b never contain NULL.
61
62   ast_string_field_init(x, 0) will reset fields to the
63   initial value while keeping the pool allocated.
64   
65   Reading the fields is much like using 'const char * const' fields in the
66   structure: you cannot write to the field or to the memory it points to.
67
68   Writing to the fields must be done using the wrapper macros listed below;
69   and assignments are always by value (i.e. strings are copied):
70   * ast_string_field_set() stores a simple value;
71   * ast_string_field_build() builds the string using a printf-style format;
72   * ast_string_field_build_va() is the varargs version of the above (for
73     portability reasons it uses two vararg arguments);
74   * variants of these function allow passing a pointer to the field
75     as an argument.
76
77   \code
78   ast_string_field_set(x, foo, "infinite loop");
79   ast_string_field_set(x, foo, NULL); // set to an empty string
80   ast_string_field_ptr_set(x, &x->bar, "right way");
81
82   ast_string_field_build(x, blah, "%d %s", zipcode, city);
83   ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
84
85   ast_string_field_build_va(x, bar, fmt, args1, args2)
86   ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
87   \endcode
88
89   When the structure instance is no longer needed, the fields
90   and their storage pool must be freed:
91   
92   \code
93   ast_string_field_free_memory(x);
94   ast_free(x);
95   \endcode
96
97   This completes the API description.
98 */
99
100 #ifndef _ASTERISK_STRINGFIELDS_H
101 #define _ASTERISK_STRINGFIELDS_H
102
103 #include "asterisk/inline_api.h"
104
105 /*!
106   \internal
107   \brief An opaque type for managed string fields in structures
108
109   Don't declare instances of this type directly; use the AST_STRING_FIELD()
110   macro instead.
111
112   In addition to the string itself, the amount of space allocated for the
113   field is stored in the two bytes immediately preceding it.
114 */
115 typedef const char * ast_string_field;
116
117 /*!
118   \internal
119   \brief A constant empty string used for fields that have no other value
120 */
121 extern const char *__ast_string_field_empty;
122
123 /*!
124   \internal
125   \brief Structure used to hold a pool of space for string fields
126 */
127 struct ast_string_field_pool {
128         struct ast_string_field_pool *prev;     /*!< pointer to the previous pool, if any */
129         size_t size;                            /*!< the total size of the pool */
130         size_t used;                            /*!< the space used in the pool */
131         size_t active;                          /*!< the amount of space actively in use by fields */
132         char base[0];                           /*!< storage space for the fields */
133 };
134
135 /*!
136   \internal
137   \brief Structure used to manage the storage for a set of string fields.
138 */
139 struct ast_string_field_mgr {
140         ast_string_field last_alloc;                    /*!< the last field allocated */
141         struct ast_string_field_pool *embedded_pool;    /*!< pointer to the embedded pool, if any */
142 #if defined(__AST_DEBUG_MALLOC)
143         const char *owner_file;                         /*!< filename of owner */
144         const char *owner_func;                         /*!< function name of owner */
145         int owner_line;                                 /*!< line number of owner */
146 #endif
147 };
148
149 /*!
150   \internal
151   \brief Attempt to 'grow' an already allocated field to a larger size
152   \param mgr Pointer to the pool manager structure
153   \param needed Amount of space needed for this field
154   \param ptr Pointer to a field within the structure
155   \return 0 on success, non-zero on failure
156
157   This function will attempt to increase the amount of space allocated to
158   an existing field to the amount requested; this is only possible if the
159   field was the last field allocated from the current storage pool and
160   the pool has enough space available. If so, the additional space will be
161   allocated to this field and the field's address will not be changed.
162 */
163 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
164                                 struct ast_string_field_pool **pool_head, size_t needed,
165                                 const ast_string_field *ptr);
166
167 /*!
168   \internal
169   \brief Allocate space for a field
170   \param mgr Pointer to the pool manager structure
171   \param needed Amount of space needed for this field
172   \param fields Pointer to the first entry of the field array
173   \return NULL on failure, an address for the field on success.
174
175   This function will allocate the requested amount of space from
176   the field pool. If the requested amount of space is not available,
177   an additional pool will be allocated.
178 */
179 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
180                                                 struct ast_string_field_pool **pool_head, size_t needed);
181
182 /*!
183   \internal
184   \brief Set a field to a complex (built) value
185   \param mgr Pointer to the pool manager structure
186   \param pool_head Pointer to the current pool
187   \param ptr Pointer to a field within the structure
188   \param format printf-style format string
189   \return nothing
190 */
191 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
192                                   struct ast_string_field_pool **pool_head,
193                                   ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
194
195 /*!
196   \internal
197   \brief Set a field to a complex (built) value
198   \param mgr Pointer to the pool manager structure
199   \param pool_head Pointer to the current pool
200   \param ptr Pointer to a field within the structure
201   \param format printf-style format string
202   \param args va_list of the args for the format_string
203   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
204   \return nothing
205 */
206 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
207                                      struct ast_string_field_pool **pool_head,
208                                      ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
209
210 /*!
211   \brief Declare a string field
212   \param name The field name
213 */
214 #define AST_STRING_FIELD(name) const ast_string_field name
215
216 /*!
217   \brief Declare the fields needed in a structure
218   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
219   Internally, string fields are stored as a pointer to the head of the pool,
220   followed by individual string fields, and then a struct ast_string_field_mgr
221   which describes the space allocated.
222   We split the two variables so they can be used as markers around the
223   field_list, and this allows us to determine how many entries are in
224   the field, and play with them.
225   In particular, for writing to the fields, we rely on __field_mgr_pool to be
226   a non-const pointer, so we know it has the same size as ast_string_field,
227   and we can use it to locate the fields.
228 */
229 #define AST_DECLARE_STRING_FIELDS(field_list) \
230         struct ast_string_field_pool *__field_mgr_pool; \
231         field_list                                      \
232         struct ast_string_field_mgr __field_mgr
233
234 /*!
235   \brief Initialize a field pool and fields
236   \param x Pointer to a structure containing fields
237   \param size Amount of storage to allocate.
238         Use 0 to reset fields to the default value,
239         and release all but the most recent pool.
240         size<0 (used internally) means free all pools.
241   \return 0 on success, non-zero on failure
242 */
243 #define ast_string_field_init(x, size) \
244         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
245
246 /*! \brief free all memory - to be called before destroying the object */
247 #define ast_string_field_free_memory(x) \
248         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__)
249
250 /*!
251  * \internal
252  * \brief internal version of ast_string_field_init
253  */
254 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
255                             int needed, const char *file, int lineno, const char *func);
256
257 /*!
258  * \brief Allocate a structure with embedded stringfields in a single allocation
259  * \param n Number of structures to allocate (see ast_calloc)
260  * \param type The type of structure to allocate
261  * \param size The number of bytes of space (minimum) to allocate for stringfields to use
262  *
263  * This function will allocate memory for one or more structures that use stringfields, and
264  * also allocate space for the stringfields and initialize the stringfield management
265  * structure embedded in the outer structure.
266  *
267  * \since 1.6.3
268  */
269 #define ast_calloc_with_stringfields(n, type, size) \
270         __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
271                                        size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
272
273 /*!
274  * \internal
275  * \brief internal version of ast_calloc_with_stringfields
276  */
277 void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
278                                                        size_t field_mgr_pool_offset, size_t pool_size, const char *file,
279                                                        int lineno, const char *func);
280
281 /*!
282   \internal
283   \brief Release a field's allocation from a pool
284   \param pool_head Pointer to the current pool
285   \param ptr Field to be released
286   \return nothing
287
288   This function will search the pool list to find the pool that contains
289   the allocation for the specified field, then remove the field's allocation
290   from that pool's 'active' count. If the pool's active count reaches zero,
291   and it is not the current pool, then it will be freed.
292  */
293 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
294                                        const ast_string_field ptr);
295
296 /* the type of storage used to track how many bytes were allocated for a field */
297
298 typedef uint16_t ast_string_field_allocation;
299
300 /*!
301   \brief Macro to provide access to the allocation field that lives immediately in front of a string field
302   \param x Pointer to the string field
303 */
304 #define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - sizeof(ast_string_field_allocation)))
305
306 /*!
307   \brief Set a field to a simple string value
308   \param x Pointer to a structure containing fields
309   \param ptr Pointer to a field within the structure
310   \param data String value to be copied into the field 
311   \return nothing
312 */
313 #define ast_string_field_ptr_set(x, ptr, data) do {                                                                     \
314         const char *__d__ = (data);                                                                                     \
315         size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;                                                              \
316         ast_string_field *__p__ = (ast_string_field *) (ptr);                                                           \
317         if (__dlen__ == 1) {                                                                                            \
318                 __ast_string_field_release_active((x)->__field_mgr_pool, *__p__);                                       \
319                 *__p__ = __ast_string_field_empty;                                                                      \
320         } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) ||                                                 \
321                    (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) ||        \
322                    (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) {    \
323                 if (*__p__ != (*ptr)) {                                                                                 \
324                         __ast_string_field_release_active((x)->__field_mgr_pool, (*ptr));                               \
325                 }                                                                                                       \
326                 memcpy(* (void **) __p__, __d__, __dlen__);                                                             \
327         }                                                                                                               \
328         } while (0)
329
330 /*!
331   \brief Set a field to a simple string value
332   \param x Pointer to a structure containing fields
333   \param field Name of the field to set
334   \param data String value to be copied into the field
335   \return nothing
336 */
337 #define ast_string_field_set(x, field, data) do {               \
338         ast_string_field_ptr_set(x, &(x)->field, data);         \
339         } while (0)
340
341 /*!
342   \brief Set a field to a complex (built) value
343   \param x Pointer to a structure containing fields
344   \param ptr Pointer to a field within the structure
345   \param fmt printf-style format string
346   \param args Arguments for format string
347   \return nothing
348 */
349 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
350         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
351
352 /*!
353   \brief Set a field to a complex (built) value
354   \param x Pointer to a structure containing fields
355   \param field Name of the field to set
356   \param fmt printf-style format string
357   \param args Arguments for format string
358   \return nothing
359 */
360 #define ast_string_field_build(x, field, fmt, args...) \
361         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
362
363 /*!
364   \brief Set a field to a complex (built) value with prebuilt va_lists.
365   \param x Pointer to a structure containing fields
366   \param ptr Pointer to a field within the structure
367   \param fmt printf-style format string
368   \param args1 Arguments for format string in va_list format
369   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
370   \return nothing
371 */
372 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
373         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2)
374
375 /*!
376   \brief Set a field to a complex (built) value
377   \param x Pointer to a structure containing fields
378   \param field Name of the field to set
379   \param fmt printf-style format string
380   \param args1 argument one
381   \param args2 argument two
382   \return nothing
383 */
384 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
385         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2)
386
387 #endif /* _ASTERISK_STRINGFIELDS_H */