add memory-pool based string field management for structures
[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 char *__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   The default amount of storage to be allocated for a field pool.
151 */
152 #define AST_STRING_FIELD_DEFAULT_POOL 512
153
154 /*!
155   \brief Declare a string field
156   \param name The field name
157 */
158 #define AST_STRING_FIELD(name) const ast_string_field name;
159
160 /*!
161   \brief Declare the fields needed in a structure
162   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
163 */
164 #define AST_DECLARE_STRING_FIELDS(field_list) \
165         ast_string_field __begin_field[0]; \
166         field_list \
167         ast_string_field __end_field[0]; \
168         struct ast_string_field_pool __field_pool;
169
170 /*!
171   \brief Get the number of string fields in a structure
172   \param x Pointer to a structure containing fields
173   \return the number of fields in the structure's definition
174 */
175 #define ast_string_field_count(x) \
176         (offsetof(typeof(*x), __end_field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
177
178 /*!
179   \brief Get the index of a field in a structure
180   \param x Pointer to a structure containing fields
181   \param field Name of the field to locate
182   \return the position (index) of the field within the structure's
183   array of fields
184 */
185 #define ast_string_field_index(x, field) \
186         (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
187
188 /*!
189   \brief Initialize a field pool and fields
190   \param x Pointer to a structure containing fields
191   \return 0 on failure, non-zero on success
192 */
193 #define ast_string_field_init(x) \
194         __ast_string_field_init(&x->__field_pool, AST_STRING_FIELD_DEFAULT_POOL, &x->__begin_field[0], ast_string_field_count(x))
195
196 /*!
197   \brief Set a field to a simple string value
198   \param x Pointer to a structure containing fields
199   \param index Index position of the field within the structure
200   \param data String value to be copied into the field
201   \return nothing
202 */
203 #define ast_string_field_index_set(x, index, data) do { \
204         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)))) \
205                 strcpy((char *) x->__begin_field[index], data); \
206         } while (0)
207
208 /*!
209   \brief Set a field to a simple string value
210   \param x Pointer to a structure containing fields
211   \param field Name of the field to set
212   \param data String value to be copied into the field
213   \return nothing
214 */
215 #define ast_string_field_set(x, field, data) \
216         ast_string_field_index_set(x, ast_string_field_index(x, field), data)
217
218 /*!
219   \brief Set a field to a simple complex (built) value
220   \param x Pointer to a structure containing fields
221   \param index Index position of the field within the structure
222   \param fmt printf-style format string
223   \param args Arguments for format string
224   \return nothing
225 */
226 #define ast_string_field_index_build(x, index, fmt, args...) do { \
227         char s; \
228         size_t needed; \
229         needed = snprintf(&s, 1, fmt, args) + 1; \
230         if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_pool, needed, &x->__begin_field[0], ast_string_field_count(x)))) \
231                 sprintf((char *) x->__begin_field[index], fmt, args); \
232         } while (0)
233
234 /*!
235   \brief Set a field to a simple complex (built) value
236   \param x Pointer to a structure containing fields
237   \param field Name of the field to set
238   \param fmt printf-style format string
239   \param args Arguments for format string
240   \return nothing
241 */
242 #define ast_string_field_build(x, field, fmt, args...) \
243         ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
244
245 /*!
246   \brief Free a field's value.
247   \param x Pointer to a structure containing fields
248   \param index Index position of the field within the structure
249   \return nothing
250
251   \note Because of the storage pool used, the memory
252   occupied by the field's value is \b not recovered; the field
253   pointer is just changed to point to an empty string.
254 */
255 #define ast_string_field_index_free(x, index) do { \
256         x->__begin_field[index] = __ast_string_field_empty; \
257         } while(0)
258
259 /*!
260   \brief Free a field's value.
261   \param x Pointer to a structure containing fields
262   \param field Name of the field to free
263   \return nothing
264
265   \note Because of the storage pool used, the memory
266   occupied by the field's value is \b not recovered; the field
267   pointer is just changed to point to an empty string.
268 */
269 #define ast_string_field_free(x, field) \
270         ast_string_field_index_free(x, ast_string_field_index(x, field))
271
272 /*!
273   \brief Free all fields (and the storage pool) in a structure
274   \param x Pointer to a structure containing fields
275   \return nothing
276
277   After calling this macro, fields can no longer be accessed in
278   structure; it should only be called immediately before freeing
279   the structure itself.
280 */
281 #define ast_string_field_free_all(x) do { \
282         int index; \
283         for (index = 0; index < ast_string_field_count(x); index ++) \
284                 ast_string_field_index_free(x, index); \
285         free(x->__field_pool.base); \
286         } while(0)
287
288 #endif /* _ASTERISK_STRINGFIELDS_H */