Doxygen fixes.
[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 <string.h>
106 #include <stdarg.h>
107 #include <stddef.h>
108
109 #include "asterisk/inline_api.h"
110 #include "asterisk/compiler.h"
111 #include "asterisk/compat.h"
112
113 /*!
114   \internal
115   \brief An opaque type for managed string fields in structures
116
117   Don't declare instances of this type directly; use the AST_STRING_FIELD()
118   macro instead.
119 */
120 typedef const char * ast_string_field;
121
122 /*!
123   \internal
124   \brief A constant empty string used for fields that have no other value
125 */
126 extern const char __ast_string_field_empty[];
127
128 /*!
129   \internal
130   \brief Structure used to hold a pool of space for string fields
131 */
132 struct ast_string_field_pool {
133         struct ast_string_field_pool *prev;     /*!< pointer to the previous pool, if any */
134         char base[0];                           /*!< storage space for the fields */
135 };
136
137 /*!
138   \internal
139   \brief Structure used to manage the storage for a set of string fields.
140   Because of the way pools are managed, we can only allocate from the topmost
141   pool, so the numbers here reflect just that.
142 */
143 struct ast_string_field_mgr {
144         size_t size;            /*!< the total size of the current pool */
145         size_t used;            /*!< the space used in the current pool */
146 };
147
148 /*!
149   \internal
150   \brief Allocate space for a field
151   \param mgr Pointer to the pool manager structure
152   \param needed Amount of space needed for this field
153   \param fields Pointer to the first entry of the field array
154   \return NULL on failure, an address for the field on success.
155
156   This function will allocate the requested amount of space from
157   the field pool. If the requested amount of space is not available,
158   an additional pool will be allocated.
159 */
160 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
161          struct ast_string_field_pool **pool_head, size_t needed);
162
163 /*!
164   \internal
165   \brief Set a field to a complex (built) value
166   \param mgr Pointer to the pool manager structure
167   \param fields Pointer to the first entry of the field array
168   \param ptr Pointer to a field within the structure
169   \param format printf-style format string
170   \return nothing
171 */
172 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
173         struct ast_string_field_pool **pool_head,
174         const ast_string_field *ptr, const char *format, ...);
175
176 /*!
177   \internal
178   \brief Set a field to a complex (built) value
179   \param mgr Pointer to the pool manager structure
180   \param fields Pointer to the first entry of the field array
181   \param ptr Pointer to a field within the structure
182   \param format printf-style format string
183   \param args va_list of the args for the format_string
184   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
185   \return nothing
186 */
187 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
188         struct ast_string_field_pool **pool_head,
189         const ast_string_field *ptr, const char *format, va_list a1, va_list a2);
190
191 /*!
192   \brief Declare a string field
193   \param name The field name
194 */
195 #define AST_STRING_FIELD(name) const ast_string_field name
196
197 /*!
198   \brief Declare the fields needed in a structure
199   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
200   Internally, string fields are stored as a pointer to the head of the pool,
201   followed by individual string fields, and then a struct ast_string_field_mgr
202   which describes the space allocated.
203   We split the two variables so they can be used as markers around the
204   field_list, and this allows us to determine how many entries are in
205   the field, and play with them.
206   In particular, for writing to the fields, we rely on __field_mgr_pool to be
207   a non-const pointer, so we know it has the same size as ast_string_field,
208   and we can use it to locate the fields.
209 */
210 #define AST_DECLARE_STRING_FIELDS(field_list) \
211         struct ast_string_field_pool *__field_mgr_pool; \
212         field_list                                      \
213         struct ast_string_field_mgr __field_mgr
214
215 /*!
216   \brief Initialize a field pool and fields
217   \param x Pointer to a structure containing fields
218   \param size Amount of storage to allocate.
219         Use 0 to reset fields to the default value,
220         and release all but the most recent pool.
221         size<0 (used internally) means free all pools.
222   \return 0 on success, non-zero on failure
223 */
224 #define ast_string_field_init(x, size) \
225         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size)
226
227 /*! \brief free all memory - to be called before destroying the object */
228 #define ast_string_field_free_memory(x) \
229         __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1)
230
231 /*! \internal \brief internal version of ast_string_field_init */
232 int __ast_string_field_init(struct ast_string_field_mgr *mgr,
233         struct ast_string_field_pool **pool_head, size_t needed);
234
235 /*!
236   \brief Set a field to a simple string value
237   \param x Pointer to a structure containing fields
238   \param ptr Pointer to a field within the structure
239   \param data String value to be copied into the field
240   \return nothing
241 */
242
243 #define ast_string_field_ptr_set(x, ptr, data) do {             \
244         const char *__d__ = (data);                             \
245         size_t __dlen__ = (__d__) ? strlen(__d__) : 0;          \
246         const char **__p__ = (const char **)(ptr);              \
247         if (__dlen__ == 0)                                      \
248                 *__p__ = __ast_string_field_empty;              \
249         else if (__dlen__ <= strlen(*__p__))                    \
250                 strcpy((char *)*__p__, __d__);                  \
251         else if ( (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__ + 1) ) ) \
252                 strcpy((char *)*__p__, __d__);                  \
253         } while (0)
254
255 /*!
256   \brief Set a field to a simple string value
257   \param x Pointer to a structure containing fields
258   \param field Name of the field to set
259   \param data String value to be copied into the field
260   \return nothing
261 */
262 #define ast_string_field_set(x, field, data)    do {            \
263         ast_string_field_ptr_set(x, &(x)->field, data);         \
264         } while (0)
265
266
267 /*!
268   \brief Set a field to a complex (built) value
269   \param x Pointer to a structure containing fields
270   \param ptr Pointer to a field within the structure
271   \param fmt printf-style format string
272   \param args Arguments for format string
273   \return nothing
274 */
275 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
276         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args)
277
278 /*!
279   \brief Set a field to a complex (built) value
280   \param x Pointer to a structure containing fields
281   \param field Name of the field to set
282   \param fmt printf-style format string
283   \param args Arguments for format string
284   \return nothing
285 */
286 #define ast_string_field_build(x, field, fmt, args...) \
287         __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args)
288
289 /*!
290   \brief Set a field to a complex (built) value with prebuilt va_lists.
291   \param x Pointer to a structure containing fields
292   \param ptr Pointer to a field within the structure
293   \param fmt printf-style format string
294   \param args1 Arguments for format string in va_list format
295   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
296   \return nothing
297 */
298 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
299         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args1, args2)
300
301 /*!
302   \brief Set a field to a complex (built) value
303   \param x Pointer to a structure containing fields
304   \param field Name of the field to set
305   \param fmt printf-style format string
306   \param args1 argument one
307   \param args2 argument two
308   \return nothing
309 */
310 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
311         __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args1, args2)
312
313 #endif /* _ASTERISK_STRINGFIELDS_H */