it does help if the compiler attribute syntax is correct
[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 (this feature is not used
61   in this code, but comes from external requirements).
62
63   ast_string_field_init(x, 0) will reset fields to the
64   initial value while keeping the pool allocated.
65   
66   Reading the fields is much like using 'const char * const' fields in the
67   structure: you cannot write to the field or to the memory it points to
68   (XXX perhaps the latter is too much of a restriction since values
69   are not shared).
70
71   Writing to the fields must be done using the wrapper macros listed below;
72   and assignments are always by value (i.e. strings are copied):
73   * ast_string_field_set() stores a simple value;
74   * ast_string_field_build() builds the string using a printf-style;
75   * ast_string_field_build_va() is the varargs version of the above (for
76     portability reasons it uses two vararg);
77   * variants of these function allow passing a pointer to the field
78     as an argument.
79   \code
80   ast_string_field_set(x, foo, "infinite loop");
81   ast_string_field_set(x, foo, NULL); // set to an empty string
82   ast_string_field_ptr_set(x, &x->bar, "right way");
83
84   ast_string_field_build(x, blah, "%d %s", zipcode, city);
85   ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
86
87   ast_string_field_build_va(x, bar, fmt, args1, args2)
88   ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
89   \endcode
90
91   When the structure instance is no longer needed, the fields
92   and their storage pool must be freed:
93   
94   \code
95   ast_string_field_free_memory(x);
96   ast_free(x);
97   \endcode
98
99   This completes the API description.
100 */
101
102 #ifndef _ASTERISK_STRINGFIELDS_H
103 #define _ASTERISK_STRINGFIELDS_H
104
105 #include "asterisk/inline_api.h"
106
107 /*!
108   \internal
109   \brief An opaque type for managed string fields in structures
110
111   Don't declare instances of this type directly; use the AST_STRING_FIELD()
112   macro instead.
113 */
114 typedef const char * ast_string_field;
115
116 /*!
117   \internal
118   \brief A constant empty string used for fields that have no other value
119 */
120 extern const char __ast_string_field_empty[];
121
122 /*!
123   \internal
124   \brief Structure used to hold a pool of space for string fields
125 */
126 struct ast_string_field_pool {
127         struct ast_string_field_pool *prev;     /*!< pointer to the previous pool, if any */
128         char base[0];                           /*!< storage space for the fields */
129 };
130
131 /*!
132   \internal
133   \brief Structure used to manage the storage for a set of string fields.
134   Because of the way pools are managed, we can only allocate from the topmost
135   pool, so the numbers here reflect just that.
136 */
137 struct ast_string_field_mgr {
138         size_t size;                            /*!< the total size of the current pool */
139         size_t used;                            /*!< the space used in the current pool */
140         ast_string_field last_alloc;            /*!< the last field allocated */
141 };
142
143 /*!
144   \internal
145   \brief Attempt to 'grow' an already allocated field to a larger size
146   \param mgr Pointer to the pool manager structure
147   \param needed Amount of space needed for this field
148   \param ptr Pointer to a field within the structure
149   \return 0 on success, non-zero on failure
150
151   This function will attempt to increase the amount of space allocated to
152   an existing field to the amount requested; this is only possible if the
153   field was the last field allocated from the current storage pool and
154   the pool has enough space available. If so, the additional space will be
155   allocated to this field and the field's address will not be changed.
156 */
157 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
158                                 const ast_string_field *ptr);
159
160 /*!
161   \internal
162   \brief Allocate space for a field
163   \param mgr Pointer to the pool manager structure
164   \param needed Amount of space needed for this field
165   \param fields Pointer to the first entry of the field array
166   \return NULL on failure, an address for the field on success.
167
168   This function will allocate the requested amount of space from
169   the field pool. If the requested amount of space is not available,
170   an additional pool will be allocated.
171 */
172 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
173                                                 struct ast_string_field_pool **pool_head, size_t needed);
174
175 /*!
176   \internal
177   \brief Set a field to a complex (built) value
178   \param mgr Pointer to the pool manager structure
179   \param fields Pointer to the first entry of the field array
180   \param ptr Pointer to a field within the structure
181   \param format printf-style format string
182   \return nothing
183 */
184 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
185                                   struct ast_string_field_pool **pool_head,
186                                   const ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
187
188 /*!
189   \internal
190   \brief Set a field to a complex (built) value
191   \param mgr Pointer to the pool manager structure
192   \param fields Pointer to the first entry of the field array
193   \param ptr Pointer to a field within the structure
194   \param format printf-style format string
195   \param args va_list of the args for the format_string
196   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
197   \return nothing
198 */
199 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
200                                      struct ast_string_field_pool **pool_head,
201                                      const ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
202
203 /*!
204   \brief Declare a string field
205   \param name The field name
206 */
207 #define AST_STRING_FIELD(name) const ast_string_field name
208
209 /*!
210   \brief Declare the fields needed in a structure
211   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
212   Internally, string fields are stored as a pointer to the head of the pool,
213   followed by individual string fields, and then a struct ast_string_field_mgr
214   which describes the space allocated.
215   We split the two variables so they can be used as markers around the
216   field_list, and this allows us to determine how many entries are in
217   the field, and play with them.
218   In particular, for writing to the fields, we rely on __field_mgr_pool to be
219   a non-const pointer, so we know it has the same size as ast_string_field,
220   and we can use it to locate the fields.
221 */
222 #define AST_DECLARE_STRING_FIELDS(field_list) \
223         struct ast_string_field_pool *__field_mgr_pool; \
224         field_list                                      \
225         struct ast_string_field_mgr __field_mgr
226
227 /*!
228   \brief Initialize a field pool and fields
229   \param x Pointer to a structure containing fields
230   \param size Amount of storage to allocate.
231         Use 0 to reset fields to the default value,
232         and release all but the most recent pool.
233         size<0 (used internally) means free all pools.
234   \return 0 on success, non-zero on failure
235 */
236 #define ast_string_field_init(x, size) \
237         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size)
238
239 /*! \brief free all memory - to be called before destroying the object */
240 #define ast_string_field_free_memory(x) \
241         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1)
242
243 /*! \internal \brief internal version of ast_string_field_init */
244 int __ast_string_field_init(struct ast_string_field_mgr *mgr,
245         struct ast_string_field_pool **pool_head, int needed);
246
247 /*!
248   \brief Set a field to a simple string value
249   \param x Pointer to a structure containing fields
250   \param ptr Pointer to a field within the structure
251   \param data String value to be copied into the field
252   \return nothing
253 */
254 #define ast_string_field_ptr_set(x, ptr, data) do {             \
255         const char *__d__ = (data);                             \
256         size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1;      \
257         const char **__p__ = (const char **) (ptr);             \
258         char *__q__; \
259         if (__dlen__ == 1)                                      \
260                 *__p__ = __ast_string_field_empty;              \
261         else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
262                 __q__ = (char *) *__p__; \
263                 memcpy(__q__, __d__, __dlen__); \
264         } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
265                 __q__ = (char *) *__p__; \
266                 memcpy(__q__, __d__, __dlen__); \
267         } \
268         } while (0)
269
270 /*!
271   \brief Set a field to a simple string value
272   \param x Pointer to a structure containing fields
273   \param field Name of the field to set
274   \param data String value to be copied into the field
275   \return nothing
276 */
277 #define ast_string_field_set(x, field, data) do {               \
278         ast_string_field_ptr_set(x, &(x)->field, data);         \
279         } while (0)
280
281 /*!
282   \brief Set a field to a complex (built) value
283   \param x Pointer to a structure containing fields
284   \param ptr Pointer to a field within the structure
285   \param fmt printf-style format string
286   \param args Arguments for format string
287   \return nothing
288 */
289 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
290         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args)
291
292 /*!
293   \brief Set a field to a complex (built) value
294   \param x Pointer to a structure containing fields
295   \param field Name of the field to set
296   \param fmt printf-style format string
297   \param args Arguments for format string
298   \return nothing
299 */
300 #define ast_string_field_build(x, field, fmt, args...) \
301         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args)
302
303 /*!
304   \brief Set a field to a complex (built) value with prebuilt va_lists.
305   \param x Pointer to a structure containing fields
306   \param ptr Pointer to a field within the structure
307   \param fmt printf-style format string
308   \param args1 Arguments for format string in va_list format
309   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
310   \return nothing
311 */
312 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
313         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args1, args2)
314
315 /*!
316   \brief Set a field to a complex (built) value
317   \param x Pointer to a structure containing fields
318   \param field Name of the field to set
319   \param fmt printf-style format string
320   \param args1 argument one
321   \param args2 argument two
322   \return nothing
323 */
324 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
325         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args1, args2)
326
327 #endif /* _ASTERISK_STRINGFIELDS_H */