Wed Jan 8 2020 09:49:51

Asterisk developer's documentation


stringfields.h
Go to the documentation of this file.
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.
61 
62  ast_string_field_init(x, 0) will reset fields to the
63  initial value while keeping the pool allocated.
64 
65  Reading the fields is much like using 'const char * const' fields in the
66  structure: you cannot write to the field or to the memory it points to.
67 
68  Writing to the fields must be done using the wrapper macros listed below;
69  and assignments are always by value (i.e. strings are copied):
70  * ast_string_field_set() stores a simple value;
71  * ast_string_field_build() builds the string using a printf-style format;
72  * ast_string_field_build_va() is the varargs version of the above (for
73  portability reasons it uses two vararg arguments);
74  * variants of these function allow passing a pointer to the field
75  as an argument.
76 
77  \code
78  ast_string_field_set(x, foo, "infinite loop");
79  ast_string_field_set(x, foo, NULL); // set to an empty string
80  ast_string_field_ptr_set(x, &x->bar, "right way");
81 
82  ast_string_field_build(x, blah, "%d %s", zipcode, city);
83  ast_string_field_ptr_build(x, &x->blah, "%d %s", zipcode, city);
84 
85  ast_string_field_build_va(x, bar, fmt, args1, args2)
86  ast_string_field_ptr_build_va(x, &x->bar, fmt, args1, args2)
87  \endcode
88 
89  When the structure instance is no longer needed, the fields
90  and their storage pool must be freed:
91 
92  \code
93  ast_string_field_free_memory(x);
94  ast_free(x);
95  \endcode
96 
97  This completes the API description.
98 */
99 
100 #ifndef _ASTERISK_STRINGFIELDS_H
101 #define _ASTERISK_STRINGFIELDS_H
102 
103 #include "asterisk/inline_api.h"
104 
105 /*!
106  \internal
107  \brief An opaque type for managed string fields in structures
108 
109  Don't declare instances of this type directly; use the AST_STRING_FIELD()
110  macro instead.
111 
112  In addition to the string itself, the amount of space allocated for the
113  field is stored in the two bytes immediately preceding it.
114 */
115 typedef const char * ast_string_field;
116 
117 /* the type of storage used to track how many bytes were allocated for a field */
118 
120 
121 /*!
122  \internal
123  \brief A constant empty string used for fields that have no other value
124 */
125 extern const char *__ast_string_field_empty;
126 
127 /*!
128  \internal
129  \brief Structure used to hold a pool of space for string fields
130  \note base is aligned so base+used can stay aligned by incrementing used with
131  aligned numbers only
132 */
134  struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
135  size_t size; /*!< the total size of the pool */
136  size_t used; /*!< the space used in the pool */
137  size_t active; /*!< the amount of space actively in use by fields */
138  char base[0] __attribute__((aligned(__alignof__(ast_string_field_allocation)))); /*!< storage space for the fields */
139 };
140 
141 /*!
142  \internal
143  \brief Structure used to manage the storage for a set of string fields.
144 */
146  ast_string_field last_alloc; /*!< the last field allocated */
147  struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */
148 #if defined(__AST_DEBUG_MALLOC)
149  const char *owner_file; /*!< filename of owner */
150  const char *owner_func; /*!< function name of owner */
151  int owner_line; /*!< line number of owner */
152 #endif
153 };
154 
155 /*!
156  \internal
157  \brief Attempt to 'grow' an already allocated field to a larger size
158  \param mgr Pointer to the pool manager structure
159  \param needed Amount of space needed for this field
160  \param ptr Pointer to a field within the structure
161  \return 0 on success, non-zero on failure
162 
163  This function will attempt to increase the amount of space allocated to
164  an existing field to the amount requested; this is only possible if the
165  field was the last field allocated from the current storage pool and
166  the pool has enough space available. If so, the additional space will be
167  allocated to this field and the field's address will not be changed.
168 */
170  struct ast_string_field_pool **pool_head, size_t needed,
171  const ast_string_field *ptr);
172 
173 /*!
174  \internal
175  \brief Allocate space for a field
176  \param mgr Pointer to the pool manager structure
177  \param needed Amount of space needed for this field
178  \param fields Pointer to the first entry of the field array
179  \return NULL on failure, an address for the field on success.
180 
181  This function will allocate the requested amount of space from
182  the field pool. If the requested amount of space is not available,
183  an additional pool will be allocated.
184 */
186  struct ast_string_field_pool **pool_head, size_t needed);
187 
188 /*!
189  \internal
190  \brief Set a field to a complex (built) value
191  \param mgr Pointer to the pool manager structure
192  \param pool_head Pointer to the current pool
193  \param ptr Pointer to a field within the structure
194  \param format printf-style format string
195  \return nothing
196 */
198  struct ast_string_field_pool **pool_head,
199  ast_string_field *ptr, const char *format, ...) __attribute__((format(printf, 4, 5)));
200 
201 /*!
202  \internal
203  \brief Set a field to a complex (built) value
204  \param mgr Pointer to the pool manager structure
205  \param pool_head Pointer to the current pool
206  \param ptr Pointer to a field within the structure
207  \param format printf-style format string
208  \param args va_list of the args for the format_string
209  \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
210  \return nothing
211 */
213  struct ast_string_field_pool **pool_head,
214  ast_string_field *ptr, const char *format, va_list a1, va_list a2) __attribute__((format(printf, 4, 0)));
215 
216 /*!
217  \brief Declare a string field
218  \param name The field name
219 */
220 #define AST_STRING_FIELD(name) const ast_string_field name
221 
222 /*!
223  \brief Declare the fields needed in a structure
224  \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one.
225  Internally, string fields are stored as a pointer to the head of the pool,
226  followed by individual string fields, and then a struct ast_string_field_mgr
227  which describes the space allocated.
228  We split the two variables so they can be used as markers around the
229  field_list, and this allows us to determine how many entries are in
230  the field, and play with them.
231  In particular, for writing to the fields, we rely on __field_mgr_pool to be
232  a non-const pointer, so we know it has the same size as ast_string_field,
233  and we can use it to locate the fields.
234 */
235 #define AST_DECLARE_STRING_FIELDS(field_list) \
236  struct ast_string_field_pool *__field_mgr_pool; \
237  field_list \
238  struct ast_string_field_mgr __field_mgr
239 
240 /*!
241  \brief Initialize a field pool and fields
242  \param x Pointer to a structure containing fields
243  \param size Amount of storage to allocate.
244  Use 0 to reset fields to the default value,
245  and release all but the most recent pool.
246  size<0 (used internally) means free all pools.
247  \return 0 on success, non-zero on failure
248 */
249 #define ast_string_field_init(x, size) \
250  __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
251 
252 /*! \brief free all memory - to be called before destroying the object */
253 #define ast_string_field_free_memory(x) \
254  __ast_string_field_init(&(x)->__field_mgr, &(x)->__field_mgr_pool, -1, __FILE__, __LINE__, __PRETTY_FUNCTION__)
255 
256 /*!
257  * \internal
258  * \brief internal version of ast_string_field_init
259  */
260 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
261  int needed, const char *file, int lineno, const char *func);
262 
263 /*!
264  * \brief Allocate a structure with embedded stringfields in a single allocation
265  * \param n Number of structures to allocate (see ast_calloc)
266  * \param type The type of structure to allocate
267  * \param size The number of bytes of space (minimum) to allocate for stringfields to use
268  *
269  * This function will allocate memory for one or more structures that use stringfields, and
270  * also allocate space for the stringfields and initialize the stringfield management
271  * structure embedded in the outer structure.
272  *
273  * \since 1.8
274  */
275 #define ast_calloc_with_stringfields(n, type, size) \
276  __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
277  size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
278 
279 /*!
280  * \internal
281  * \brief internal version of ast_calloc_with_stringfields
282  */
283 void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
284  size_t field_mgr_pool_offset, size_t pool_size, const char *file,
285  int lineno, const char *func);
286 
287 /*!
288  \internal
289  \brief Release a field's allocation from a pool
290  \param pool_head Pointer to the current pool
291  \param ptr Field to be released
292  \return nothing
293 
294  This function will search the pool list to find the pool that contains
295  the allocation for the specified field, then remove the field's allocation
296  from that pool's 'active' count. If the pool's active count reaches zero,
297  and it is not the current pool, then it will be freed.
298  */
300  const ast_string_field ptr);
301 
302 /*!
303  \brief Macro to provide access to the allocation field that lives immediately in front of a string field
304  \param x Pointer to the string field
305 
306  Note that x must be a pointer to a byte-sized type -- normally (char *) -- or this calculation
307  would break horribly
308 */
309 #define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - __alignof__(ast_string_field_allocation)))
310 
311 /*!
312  \brief Set a field to a simple string value
313  \param x Pointer to a structure containing fields
314  \param ptr Pointer to a field within the structure
315  \param data String value to be copied into the field
316  \return nothing
317 */
318 #define ast_string_field_ptr_set(x, ptr, data) do { \
319  const char *__d__ = (data); \
320  size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
321  ast_string_field *__p__ = (ast_string_field *) (ptr); \
322  ast_string_field target = *__p__; \
323  if (__dlen__ == 1) { \
324  __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \
325  *__p__ = __ast_string_field_empty; \
326  } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) || \
327  (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) || \
328  (target = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
329  if (target != *__p__) { \
330  __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \
331  *__p__ = target; \
332  } \
333  memcpy(* (void **) __p__, __d__, __dlen__); \
334  } \
335  } while (0)
336 
337 /*!
338  \brief Set a field to a simple string value
339  \param x Pointer to a structure containing fields
340  \param field Name of the field to set
341  \param data String value to be copied into the field
342  \return nothing
343 */
344 #define ast_string_field_set(x, field, data) do { \
345  ast_string_field_ptr_set(x, &(x)->field, data); \
346  } while (0)
347 
348 /*!
349  \brief Set a field to a complex (built) value
350  \param x Pointer to a structure containing fields
351  \param ptr Pointer to a field within the structure
352  \param fmt printf-style format string
353  \param args Arguments for format string
354  \return nothing
355 */
356 #define ast_string_field_ptr_build(x, ptr, fmt, args...) \
357  __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args)
358 
359 /*!
360  \brief Set a field to a complex (built) value
361  \param x Pointer to a structure containing fields
362  \param field Name of the field to set
363  \param fmt printf-style format string
364  \param args Arguments for format string
365  \return nothing
366 */
367 #define ast_string_field_build(x, field, fmt, args...) \
368  __ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args)
369 
370 /*!
371  \brief Set a field to a complex (built) value with prebuilt va_lists.
372  \param x Pointer to a structure containing fields
373  \param ptr Pointer to a field within the structure
374  \param fmt printf-style format string
375  \param args1 Arguments for format string in va_list format
376  \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
377  \return nothing
378 */
379 #define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
380  __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) ptr, fmt, args1, args2)
381 
382 /*!
383  \brief Set a field to a complex (built) value
384  \param x Pointer to a structure containing fields
385  \param field Name of the field to set
386  \param fmt printf-style format string
387  \param args1 argument one
388  \param args2 argument two
389  \return nothing
390 */
391 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
392  __ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, (ast_string_field *) &(x)->field, fmt, args1, args2)
393 
394 #endif /* _ASTERISK_STRINGFIELDS_H */
void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, ast_string_field *ptr, const char *format,...)
Definition: utils.c:2011
uint16_t ast_string_field_allocation
Definition: stringfields.h:119
struct ast_string_field_pool * embedded_pool
Definition: stringfields.h:147
int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, size_t needed, const ast_string_field *ptr)
Definition: utils.c:1888
void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, ast_string_field *ptr, const char *format, va_list a1, va_list a2)
Definition: utils.c:1935
void *attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset, size_t field_mgr_pool_offset, size_t pool_size, const char *file, int lineno, const char *func)
Definition: utils.c:2026
const char * __ast_string_field_empty
Definition: utils.c:1725
const char * ast_string_field
Definition: stringfields.h:115
Inlinable API function macro.
void __ast_string_field_release_active(struct ast_string_field_pool *pool_head, const ast_string_field ptr)
Definition: utils.c:1910
#define attribute_malloc
Definition: compiler.h:59
ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, size_t needed)
Definition: utils.c:1847
struct ast_string_field_pool * prev
Definition: stringfields.h:134
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, int needed, const char *file, int lineno, const char *func)
Definition: utils.c:1780
static snd_pcm_format_t format
Definition: chan_alsa.c:93
ast_string_field last_alloc
Definition: stringfields.h:146