ensure that string field 'build' operation only evaluates arguments one time
[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(name);
35                   AST_STRING_FIELD(address);
36                   AST_STRING_FIELD(password);
37           );
38           long x2;
39   };
40   \endcode
41   
42   When an instance of this structure is allocated, the fields
43   (and the pool of storage for them) must be initialized:
44   
45   \code
46   struct sample_fields *sample;
47   
48   sample = calloc(1, sizeof(*sample));
49   if (sample) {
50           if (!ast_string_field_init(sample)) {
51                   free(sample);
52                   sample = NULL;
53           }
54   }
55   
56   if (!sample) {
57   ...
58   }
59   \endcode
60   
61   Fields will default to pointing to an empty string, and will
62   revert to that when ast_string_field_free() is called. This means
63   that a string field will \b never contain NULL.
64   
65   Using the fields is much like using regular 'char *' fields
66   in the structure, except that writing into them must be done
67   using wrapper macros defined in this file.
68   
69   Storing simple values into fields can be done using ast_string_field_set();
70   more complex values (using printf-style format strings) can be stored
71   using ast_string_field_build().
72   
73   When the structure instance is no longer needed, the fields
74   and their storage pool must be freed:
75   
76   \code
77   ast_string_field_free_all(sample);
78   free(sample);
79   \endcode
80 */
81
82 #ifndef _ASTERISK_STRINGFIELDS_H
83 #define _ASTERISK_STRINGFIELDS_H
84
85 #include <string.h>
86 #include <stdarg.h>
87 #include <stddef.h>
88
89 #include "asterisk/inline_api.h"
90 #include "asterisk/compiler.h"
91 #include "asterisk/compat.h"
92
93 /*!
94   \internal
95   \brief An opaque type for managed string fields in structures
96
97   Don't declare instances of this type directly; use the AST_STRING_FIELD()
98   macro instead.
99 */
100 typedef const char * ast_string_field;
101
102 /*!
103   \internal
104   \brief A constant empty string used for fields that have no other value
105 */
106 extern const char *__ast_string_field_empty;
107
108 /*!
109   \internal
110   \brief Structure used to manage the storage for a field pool
111 */
112 struct ast_string_field_pool {
113         char *base;     /*!< the address of the pool's base in memory */
114         size_t size;    /*!< the total size of the pool */
115         size_t space;   /*!< the space available in the pool */
116         size_t used;    /*!< the space used in the pool */
117 };
118
119 /*!
120   \internal
121   \brief Initialize a field pool and fields
122   \param pool Pointer to the pool structure
123   \param size Amount of storage to allocate
124   \param fields Pointer to the first entry of the field array
125   \param num_fields Number of fields in the array
126   \return 0 on failure, non-zero on success
127 */
128 int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
129                             ast_string_field *fields, int num_fields);
130
131 /*!
132   \internal
133   \brief Allocate space for field in the pool
134   \param pool Pointer to the pool structure
135   \param needed Amount of space needed for this field
136   \param fields Pointer to the first entry of the field array
137   \param num_fields Number of fields in the array
138   \return NULL on failure, an address for the field on success
139
140   This function will allocate the requested amount of space from
141   the field pool. If the requested amount of space is not available,
142   the pool will be expanded until enough space becomes available,
143   and the existing fields stored there will be updated to point
144   into the new pool.
145 */
146 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
147                                                 ast_string_field *fields, int num_fields);
148
149 /*!
150   \internal
151   \brief Set a field to a complex (built) value
152   \param pool Pointer to the pool structure
153   \param fields Pointer to the first entry of the field array
154   \param num_fields Number of fields in the array
155   \param index Index position of the field within the structure
156   \param format printf-style format string
157   \return nothing
158 */
159 void __ast_string_field_index_build(struct ast_string_field_pool *pool,
160                                     ast_string_field *fields, int num_fields,
161                                     int index, const char *format, ...);
162
163 /*!
164   The default amount of storage to be allocated for a field pool.
165 */
166 #define AST_STRING_FIELD_DEFAULT_POOL 512
167
168 /*!
169   \brief Declare a string field
170   \param name The field name
171 */
172 #define AST_STRING_FIELD(name) const ast_string_field name;
173
174 /*!
175   \brief Declare the fields needed in a structure
176   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
177 */
178 #define AST_DECLARE_STRING_FIELDS(field_list) \
179         ast_string_field __begin_field[0]; \
180         field_list \
181         ast_string_field __end_field[0]; \
182         struct ast_string_field_pool __field_pool;
183
184 /*!
185   \brief Get the number of string fields in a structure
186   \param x Pointer to a structure containing fields
187   \return the number of fields in the structure's definition
188 */
189 #define ast_string_field_count(x) \
190         (offsetof(typeof(*x), __end_field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
191
192 /*!
193   \brief Get the index of a field in a structure
194   \param x Pointer to a structure containing fields
195   \param field Name of the field to locate
196   \return the position (index) of the field within the structure's
197   array of fields
198 */
199 #define ast_string_field_index(x, field) \
200         (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
201
202 /*!
203   \brief Initialize a field pool and fields
204   \param x Pointer to a structure containing fields
205   \return 0 on failure, non-zero on success
206 */
207 #define ast_string_field_init(x) \
208         __ast_string_field_init(&x->__field_pool, AST_STRING_FIELD_DEFAULT_POOL, &x->__begin_field[0], ast_string_field_count(x))
209
210 /*!
211   \brief Set a field to a simple string value
212   \param x Pointer to a structure containing fields
213   \param index Index position of the field within the structure
214   \param data String value to be copied into the field
215   \return nothing
216 */
217 #define ast_string_field_index_set(x, index, data) do { \
218         if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_pool, strlen(data) + 1, &x->__begin_field[0], ast_string_field_count(x)))) \
219                 strcpy((char *) x->__begin_field[index], data); \
220         } while (0)
221
222 /*!
223   \brief Set a field to a simple string value
224   \param x Pointer to a structure containing fields
225   \param field Name of the field to set
226   \param data String value to be copied into the field
227   \return nothing
228 */
229 #define ast_string_field_set(x, field, data) \
230         ast_string_field_index_set(x, ast_string_field_index(x, field), data)
231
232 /*!
233   \brief Set a field to a complex (built) value
234   \param x Pointer to a structure containing fields
235   \param index Index position of the field within the structure
236   \param fmt printf-style format string
237   \param args Arguments for format string
238   \return nothing
239 */
240 #define ast_string_field_index_build(x, index, fmt, args...) \
241         __ast_string_field_index_build(&x->__field_pool, &x->__begin_field[0], ast_string_field_count(x), index, fmt, args)
242
243 /*!
244   \brief Set a field to a complex (built) value
245   \param x Pointer to a structure containing fields
246   \param field Name of the field to set
247   \param fmt printf-style format string
248   \param args Arguments for format string
249   \return nothing
250 */
251 #define ast_string_field_build(x, field, fmt, args...) \
252         ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
253
254 /*!
255   \brief Free a field's value.
256   \param x Pointer to a structure containing fields
257   \param index Index position of the field within the structure
258   \return nothing
259
260   \note Because of the storage pool used, the memory
261   occupied by the field's value is \b not recovered; the field
262   pointer is just changed to point to an empty string.
263 */
264 #define ast_string_field_index_free(x, index) do { \
265         x->__begin_field[index] = __ast_string_field_empty; \
266         } while(0)
267
268 /*!
269   \brief Free a field's value.
270   \param x Pointer to a structure containing fields
271   \param field Name of the field to free
272   \return nothing
273
274   \note Because of the storage pool used, the memory
275   occupied by the field's value is \b not recovered; the field
276   pointer is just changed to point to an empty string.
277 */
278 #define ast_string_field_free(x, field) \
279         ast_string_field_index_free(x, ast_string_field_index(x, field))
280
281 /*!
282   \brief Free all fields (and the storage pool) in a structure
283   \param x Pointer to a structure containing fields
284   \return nothing
285
286   After calling this macro, fields can no longer be accessed in
287   structure; it should only be called immediately before freeing
288   the structure itself.
289 */
290 #define ast_string_field_free_all(x) do { \
291         int index; \
292         for (index = 0; index < ast_string_field_count(x); index ++) \
293                 ast_string_field_index_free(x, index); \
294         free(x->__field_pool.base); \
295         } while(0)
296
297 #endif /* _ASTERISK_STRINGFIELDS_H */