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