Merged revisions 45408 via svnmerge from
[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, 256)) {
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 hold a pool of space for string fields
111 */
112 struct ast_string_field_pool {
113         struct ast_string_field_pool *prev;     /*!< pointer to the previous pool, if any */
114         char base[0];                           /*!< storage space for the fields */
115 };
116
117 /*!
118   \internal
119   \brief Structure used to manage the storage for a set of string fields
120 */
121 struct ast_string_field_mgr {
122         struct ast_string_field_pool *pool;     /*!< the address of the pool's structure */
123         size_t size;                            /*!< the total size of the current pool */
124         size_t space;                           /*!< the space available in the current pool */
125         size_t used;                            /*!< the space used in the current pool */
126 };
127
128 /*!
129   \internal
130   \brief Initialize a field pool manager and fields
131   \param mgr Pointer to the pool manager structure
132   \param size Amount of storage to allocate
133   \param fields Pointer to the first entry of the field array
134   \param num_fields Number of fields in the array
135   \return 0 on success, non-zero on failure
136 */
137 int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
138                             ast_string_field *fields, int num_fields);
139
140 /*!
141   \internal
142   \brief Allocate space for a field
143   \param mgr Pointer to the pool manager structure
144   \param needed Amount of space needed for this field
145   \param fields Pointer to the first entry of the field array
146   \param num_fields Number of fields in the array
147   \return NULL on failure, an address for the field on success
148
149   This function will allocate the requested amount of space from
150   the field pool. If the requested amount of space is not available,
151   an additional pool will be allocated.
152 */
153 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
154                                                 ast_string_field *fields, int num_fields);
155
156 /*!
157   \internal
158   \brief Set a field to a complex (built) value
159   \param mgr Pointer to the pool manager structure
160   \param fields Pointer to the first entry of the field array
161   \param num_fields Number of fields in the array
162   \param index Index position of the field within the structure
163   \param format printf-style format string
164   \return nothing
165 */
166 void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
167                                     ast_string_field *fields, int num_fields,
168                                     int index, const char *format, ...);
169
170 /*!
171   \brief Declare a string field
172   \param name The field name
173 */
174 #define AST_STRING_FIELD(name) const ast_string_field name
175
176 /*!
177   \brief Declare the fields needed in a structure
178   \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
179 */
180 #define AST_DECLARE_STRING_FIELDS(field_list) \
181         ast_string_field __begin_field[0]; \
182         field_list \
183         ast_string_field __end_field[0]; \
184         struct ast_string_field_mgr __field_mgr
185
186 /*!
187   \brief Get the number of string fields in a structure
188   \param x Pointer to a structure containing fields
189   \return the number of fields in the structure's definition
190 */
191 #define ast_string_field_count(x) \
192         (offsetof(typeof(*(x)), __end_field) - offsetof(typeof(*(x)), __begin_field)) / sizeof(ast_string_field)
193
194 /*!
195   \brief Get the index of a field in a structure
196   \param x Pointer to a structure containing fields
197   \param field Name of the field to locate
198   \return the position (index) of the field within the structure's
199   array of fields
200 */
201 #define ast_string_field_index(x, field) \
202         (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
203
204 /*!
205   \brief Initialize a field pool and fields
206   \param x Pointer to a structure containing fields
207   \param size Amount of storage to allocate
208   \return 0 on success, non-zero on failure
209 */
210 #define ast_string_field_init(x, size) \
211         __ast_string_field_init(&(x)->__field_mgr, size, &(x)->__begin_field[0], ast_string_field_count(x))
212
213 /*!
214   \brief Set a field to a simple string value
215   \param x Pointer to a structure containing fields
216   \param index Index position of the field within the structure
217   \param data String value to be copied into the field
218   \return nothing
219 */
220 #define ast_string_field_index_set(x, index, data) do { \
221     char *__zz__ = (char*)(x)->__begin_field[index]; \
222     int __dlen__ = strlen(data); \
223     if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
224     } else { \
225      if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
226            strcpy(__zz__, data); \
227      } else { \
228        if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
229                strcpy((char*)(x)->__begin_field[index], data); \
230          } \
231         } \
232    } while (0)
233
234 #ifdef FOR_TEST
235 #define ast_string_field_index_logset(x, index, data, logstr) do { \
236     char *__zz__ = (char*)(x)->__begin_field[index]; \
237     int __dlen__ = strlen(data); \
238     if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
239     } else { \
240      if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
241        ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
242            strcpy(__zz__, data); \
243      } else { \
244        ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
245        if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
246                strcpy((char*)(x)->__begin_field[index], data); \
247          } \
248         } \
249    } while (0)
250 #endif
251
252 /*!
253   \brief Set a field to a simple string value
254   \param x Pointer to a structure containing fields
255   \param field Name of the field to set
256   \param data String value to be copied into the field
257   \return nothing
258 */
259 #define ast_string_field_set(x, field, data) \
260         ast_string_field_index_set(x, ast_string_field_index(x, field), data)
261
262 #ifdef FOR_TEST
263 #define ast_string_field_logset(x, field, data, logstr) \
264         ast_string_field_index_logset(x, ast_string_field_index(x, field), data, logstr)
265 #endif
266
267 /*!
268   \brief Set a field to a complex (built) value
269   \param x Pointer to a structure containing fields
270   \param index Index position of the 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_index_build(x, index, fmt, args...) \
276         __ast_string_field_index_build(&(x)->__field_mgr, &(x)->__begin_field[0], ast_string_field_count(x), index, 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_index_build(x, ast_string_field_index(x, field), fmt, args)
288
289 /*!
290   \brief Free a field's value.
291   \param x Pointer to a structure containing fields
292   \param index Index position of the field within the structure
293   \return nothing
294
295   \note Because of the storage pool used, the memory
296   occupied by the field's value is \b not recovered; the field
297   pointer is just changed to point to an empty string.
298 */
299 #define ast_string_field_index_free(x, index) do { \
300         (x)->__begin_field[index] = __ast_string_field_empty; \
301         } while(0)
302
303 /*!
304   \brief Free a field's value.
305   \param x Pointer to a structure containing fields
306   \param field Name of the field to free
307   \return nothing
308
309   \note Because of the storage pool used, the memory
310   occupied by the field's value is \b not recovered; the field
311   pointer is just changed to point to an empty string.
312 */
313 #define ast_string_field_free(x, field) \
314         ast_string_field_index_free(x, ast_string_field_index(x, field))
315
316 /*!
317   \brief Free the stringfield storage pools attached to a structure
318   \param x Pointer to a structure containing fields
319   \return nothing
320
321   After calling this macro, fields can no longer be accessed in
322   structure; it should only be called immediately before freeing
323   the structure itself.
324 */
325 #define ast_string_field_free_pools(x) do { \
326         struct ast_string_field_pool *this, *prev; \
327         for (this = (x)->__field_mgr.pool; this; this = prev) { \
328                 prev = this->prev; \
329                 free(this); \
330         } \
331         } while(0)
332
333 /*!
334   \brief Free the stringfields in a structure
335   \param x Pointer to a structure containing fields
336   \return nothing
337
338   After calling this macro, the most recently allocated pool
339   attached to the structure will be available for use by
340   stringfields again.
341 */
342 #define ast_string_field_free_all(x) do { \
343         int index; \
344         for (index = 0; index < ast_string_field_count(x); index++) \
345                 ast_string_field_index_free(x, index); \
346         (x)->__field_mgr.used = 0; \
347         (x)->__field_mgr.space = (x)->__field_mgr.size; \
348         } while(0)
349
350 #endif /* _ASTERISK_STRINGFIELDS_H */