2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2006, Digium, Inc.
6 * Kevin P. Fleming <kpfleming@digium.com>
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.
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.
20 \brief String fields in structures
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
27 Using this functionality is quite simple. An example structure
28 with three fields is defined like this:
31 struct sample_fields {
33 AST_DECLARE_STRING_FIELDS(
34 AST_STRING_FIELD(foo);
35 AST_STRING_FIELD(bar);
36 AST_STRING_FIELD(blah);
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
47 struct sample_fields *x;
49 x = ast_calloc(1, sizeof(*x));
50 if (x == NULL || ast_string_field_init(x, 252)) {
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).
63 ast_string_field_init(x, 0) will reset fields to the
64 initial value while keeping the pool allocated.
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
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
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");
84 ast_string_field_build(x, blah, "%d %s", zipcode, city);
85 ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
87 ast_string_field_build_va(x, bar, fmt, args1, args2)
88 ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
91 When the structure instance is no longer needed, the fields
92 and their storage pool must be freed:
95 ast_string_field_free_memory(x);
99 This completes the API description.
102 #ifndef _ASTERISK_STRINGFIELDS_H
103 #define _ASTERISK_STRINGFIELDS_H
105 #include "asterisk/inline_api.h"
109 \brief An opaque type for managed string fields in structures
111 Don't declare instances of this type directly; use the AST_STRING_FIELD()
114 typedef const char * ast_string_field;
118 \brief A constant empty string used for fields that have no other value
120 extern const char __ast_string_field_empty[];
124 \brief Structure used to hold a pool of space for string fields
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 */
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.
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 ast_string_field last_alloc; /*!< the last field allocated */
145 \brief Attempt to 'grow' an already allocated field to a larger size
146 \param mgr Pointer to the pool manager structure
147 \param needed Amount of space needed for this field
148 \param ptr Pointer to a field within the structure
149 \return 0 on success, non-zero on failure
151 This function will attempt to increase the amount of space allocated to
152 an existing field to the amount requested; this is only possible if the
153 field was the last field allocated from the current storage pool and
154 the pool has enough space available. If so, the additional space will be
155 allocated to this field and the field's address will not be changed.
157 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
158 const ast_string_field *ptr);
162 \brief Allocate space for a field
163 \param mgr Pointer to the pool manager structure
164 \param needed Amount of space needed for this field
165 \param fields Pointer to the first entry of the field array
166 \return NULL on failure, an address for the field on success.
168 This function will allocate the requested amount of space from
169 the field pool. If the requested amount of space is not available,
170 an additional pool will be allocated.
172 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
173 struct ast_string_field_pool **pool_head, size_t needed);
177 \brief Set a field to a complex (built) value
178 \param mgr Pointer to the pool manager structure
179 \param fields Pointer to the first entry of the field array
180 \param ptr Pointer to a field within the structure
181 \param format printf-style format string
184 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
185 struct ast_string_field_pool **pool_head,
186 const ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
190 \brief Set a field to a complex (built) value
191 \param mgr Pointer to the pool manager structure
192 \param fields Pointer to the first entry of the field array
193 \param ptr Pointer to a field within the structure
194 \param format printf-style format string
195 \param args va_list of the args for the format_string
196 \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
199 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
200 struct ast_string_field_pool **pool_head,
201 const ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
204 \brief Declare a string field
205 \param name The field name
207 #define AST_STRING_FIELD(name) const ast_string_field name
210 \brief Declare the fields needed in a structure
211 \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
212 Internally, string fields are stored as a pointer to the head of the pool,
213 followed by individual string fields, and then a struct ast_string_field_mgr
214 which describes the space allocated.
215 We split the two variables so they can be used as markers around the
216 field_list, and this allows us to determine how many entries are in
217 the field, and play with them.
218 In particular, for writing to the fields, we rely on __field_mgr_pool to be
219 a non-const pointer, so we know it has the same size as ast_string_field,
220 and we can use it to locate the fields.
222 #define AST_DECLARE_STRING_FIELDS(field_list) \
223 struct ast_string_field_pool *__field_mgr_pool; \
225 struct ast_string_field_mgr __field_mgr
228 \brief Initialize a field pool and fields
229 \param x Pointer to a structure containing fields
230 \param size Amount of storage to allocate.
231 Use 0 to reset fields to the default value,
232 and release all but the most recent pool.
233 size<0 (used internally) means free all pools.
234 \return 0 on success, non-zero on failure
236 #define ast_string_field_init(x, size) \
237 __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size)
239 /*! \brief free all memory - to be called before destroying the object */
240 #define ast_string_field_free_memory(x) \
241 __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1)
243 /*! \internal \brief internal version of ast_string_field_init */
244 int __ast_string_field_init(struct ast_string_field_mgr *mgr,
245 struct ast_string_field_pool **pool_head, int needed);
248 \brief Set a field to a simple string value
249 \param x Pointer to a structure containing fields
250 \param ptr Pointer to a field within the structure
251 \param data String value to be copied into the field
254 #define ast_string_field_ptr_set(x, ptr, data) do { \
255 const char *__d__ = (data); \
256 size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
257 const char **__p__ = (const char **) (ptr); \
260 *__p__ = __ast_string_field_empty; \
261 else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
262 __q__ = (char *) *__p__; \
263 memcpy(__q__, __d__, __dlen__); \
264 } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
265 __q__ = (char *) *__p__; \
266 memcpy(__q__, __d__, __dlen__); \
271 \brief Set a field to a simple string value
272 \param x Pointer to a structure containing fields
273 \param field Name of the field to set
274 \param data String value to be copied into the field
277 #define ast_string_field_set(x, field, data) do { \
278 ast_string_field_ptr_set(x, &(x)->field, data); \
282 \brief Set a field to a complex (built) value
283 \param x Pointer to a structure containing fields
284 \param ptr Pointer to a field within the structure
285 \param fmt printf-style format string
286 \param args Arguments for format string
289 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
290 __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args)
293 \brief Set a field to a complex (built) value
294 \param x Pointer to a structure containing fields
295 \param field Name of the field to set
296 \param fmt printf-style format string
297 \param args Arguments for format string
300 #define ast_string_field_build(x, field, fmt, args...) \
301 __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args)
304 \brief Set a field to a complex (built) value with prebuilt va_lists.
305 \param x Pointer to a structure containing fields
306 \param ptr Pointer to a field within the structure
307 \param fmt printf-style format string
308 \param args1 Arguments for format string in va_list format
309 \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
312 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
313 __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args1, args2)
316 \brief Set a field to a complex (built) value
317 \param x Pointer to a structure containing fields
318 \param field Name of the field to set
319 \param fmt printf-style format string
320 \param args1 argument one
321 \param args2 argument two
324 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
325 __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args1, args2)
327 #endif /* _ASTERISK_STRINGFIELDS_H */