[asterisk-commits] rizzo: branch rizzo/video_v2 r87742 - in /team/rizzo/video_v2: channels/ incl...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Oct 30 18:30:20 CDT 2007


Author: rizzo
Date: Tue Oct 30 18:30:20 2007
New Revision: 87742

URL: http://svn.digium.com/view/asterisk?view=rev&rev=87742
Log:
almost final (except for remaining bugfixes) cleanup of stringfields.
In this episode:
+ as proposed in the mailing list, change the API to use _ptr_ instead of
  _index_ to fields. I think this is far more natural for the programmer,
  and simpler to implement. For the records, this feature is used only
  in one place in the code.

+ try to improve documentation of the stringfields API;

+ simplify the structure of memory pools, now saving one size_t per pool
  entry.

What remains to do now is rename internal APIs to make a better
job at hiding them, and fix ast_string_field_free_all to release
unusable pools.


Modified:
    team/rizzo/video_v2/channels/chan_sip.c
    team/rizzo/video_v2/include/asterisk/stringfields.h
    team/rizzo/video_v2/main/utils.c

Modified: team/rizzo/video_v2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/chan_sip.c?view=diff&rev=87742&r1=87741&r2=87742
==============================================================================
--- team/rizzo/video_v2/channels/chan_sip.c (original)
+++ team/rizzo/video_v2/channels/chan_sip.c Tue Oct 30 18:30:20 2007
@@ -12430,13 +12430,13 @@
 	/* table of recognised keywords, and places where they should be copied */
 	const struct x {
 		const char *key;
-		int field_index;
+		const ast_string_field *field;
 	} *i, keys[] = {
-		{ "realm=", ast_string_field_index(p, realm) },
-		{ "nonce=", ast_string_field_index(p, nonce) },
-		{ "opaque=", ast_string_field_index(p, opaque) },
-		{ "qop=", ast_string_field_index(p, qop) },
-		{ "domain=", ast_string_field_index(p, domain) },
+		{ "realm=", &p->realm },
+		{ "nonce=", &p->nonce },
+		{ "opaque=", &p->opaque },
+		{ "qop=", &p->qop },
+		{ "domain=", &p->domain },
 		{ NULL, 0 },
 	};
 
@@ -12464,7 +12464,7 @@
 				separator = ",";
 			}
 			strsep(&c, separator); /* clear separator and move ptr */
-			ast_string_field_index_set(p, i->field_index, src);
+			ast_string_field_ptr_set(p, i->field, src);
 			break;
 		}
 		if (i->key == NULL) /* not found, try ',' */

Modified: team/rizzo/video_v2/include/asterisk/stringfields.h
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/include/asterisk/stringfields.h?view=diff&rev=87742&r1=87741&r2=87742
==============================================================================
--- team/rizzo/video_v2/include/asterisk/stringfields.h (original)
+++ team/rizzo/video_v2/include/asterisk/stringfields.h Tue Oct 30 18:30:20 2007
@@ -24,16 +24,16 @@
   as fixed-size buffers or requiring individual allocations for
   for each field.
   
-  Using this functionality is quite simple... an example structure
+  Using this functionality is quite simple. An example structure
   with three fields is defined like this:
   
   \code
   struct sample_fields {
 	  int x1;
 	  AST_DECLARE_STRING_FIELDS(
-		  AST_STRING_FIELD(name);
-		  AST_STRING_FIELD(address);
-		  AST_STRING_FIELD(password);
+		  AST_STRING_FIELD(foo);
+		  AST_STRING_FIELD(bar);
+		  AST_STRING_FIELD(blah);
 	  );
 	  long x2;
   };
@@ -54,22 +54,35 @@
   }
   
   if (!sample) {
-  ...
+  ... handle error
   }
   \endcode
   
   Fields will default to pointing to an empty string, and will
   revert to that when ast_string_field_set() is called with a NULL
-  argument: a string field will \b never contain NULL.
-  
-  Using the fields is much like using regular 'char *' fields
+  argument: a string field will \b never contain NULL (this is not
+  needed in this code, but comes from external requirements).
+  
+  Using the fields is much like using regular 'const char *' fields
   in the structure, except that writing into them must be done
-  using wrapper macros defined in this file.
-  
+  using wrapper macros defined in this file, and assignments are
+  always by value (i.e. strings are copied).
   Storing simple values into fields can be done using ast_string_field_set();
   more complex values (using printf-style format strings) can be stored
-  using ast_string_field_build().
-  
+  using ast_string_field_build(). Variant of these function allow passing
+  a pointer to the field as an argument:
+  \code
+  ast_string_field_set(sample, foo, "infinite loop");
+  ast_string_field_set(sample, foo, NULL); // set to an empty string
+  ast_string_field_ptr_set(sample, &sample->bar, "right way");
+  ast_string_field_build(sample, blah, "%d %s", zipcode, city);
+  ast_string_field_ptr_build(sample, &sample->blah, "%d %s", zipcode, city);
+  \endcode
+  There are two more varargs versions of the 'build' functions,
+  and ast_string_field_free_all() which is used to clear all stringfields
+  to the default values (meant to be used when resetting a
+  structure to its initial value).
+
   When the structure instance is no longer needed, the fields
   and their storage pool must be freed:
   
@@ -121,9 +134,8 @@
   pool, so the numbers here reflect just that.
 */
 struct ast_string_field_mgr {
-	size_t size;				/*!< the total size of the current pool */
-	size_t space;				/*!< the space available in the current pool */
-	size_t used;				/*!< the space used in the current pool */
+	size_t size;		/*!< the total size of the current pool */
+	size_t used;		/*!< the space used in the current pool */
 };
 
 /*!
@@ -157,28 +169,28 @@
   \brief Set a field to a complex (built) value
   \param mgr Pointer to the pool manager structure
   \param fields Pointer to the first entry of the field array
-  \param index Index position of the field within the structure
+  \param ptr Pointer to a field within the structure
   \param format printf-style format string
   \return nothing
 */
-void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
+void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
 	struct ast_string_field_pool **pool_head,
-	int index, const char *format, ...);
+	const ast_string_field *ptr, const char *format, ...);
 
 /*!
   \internal
   \brief Set a field to a complex (built) value
   \param mgr Pointer to the pool manager structure
   \param fields Pointer to the first entry of the field array
-  \param index Index position of the field within the structure
+  \param ptr Pointer to a field within the structure
   \param format printf-style format string
   \param args va_list of the args for the format_string
   \param args_again a copy of the first va_list for the sake of bsd not having a copy routine
   \return nothing
 */
-void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
+void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
 	struct ast_string_field_pool **pool_head,
-	int index, const char *format, va_list a1, va_list a2);
+	const ast_string_field *ptr, const char *format, va_list a1, va_list a2);
 
 /*!
   \brief Declare a string field
@@ -195,12 +207,9 @@
   We split the two variables so they can be used as markers around the
   field_list, and this allows us to determine how many entries are in
   the field, and play with them.
-  In particular, for writing to the field, we rely on __field_mgr_pool to be
-  a non-const pointer, so 1) we know it has the same size as ast_string_field,
-  and 2) we can cast it to const char * and use it as the base of an array to
-  write to the fields.
-  Because of this, the low-level functions to manipulate stringfields
-  use the index instead of the name of the field.
+  In particular, for writing to the fields, we rely on __field_mgr_pool to be
+  a non-const pointer, so we know it has the same size as ast_string_field,
+  and we can use it to locate the fields.
 */
 #define AST_DECLARE_STRING_FIELDS(field_list) \
 	struct ast_string_field_pool *__field_mgr_pool;	\
@@ -208,16 +217,6 @@
 	struct ast_string_field_mgr __field_mgr
 
 /*!
-  \brief Get the index of a field in a structure
-  \param x Pointer to a structure containing fields
-  \param field Name of the field to locate
-  \return the position (index) of the field within the structure's
-  array of fields
-*/
-#define ast_string_field_index(x, field) \
-	(offsetof(typeof(*x), field) - offsetof(typeof(*x), __field_mgr_pool) - sizeof(ast_string_field)) / sizeof(ast_string_field)
-
-/*!
   \brief Initialize a field pool and fields
   \param x Pointer to a structure containing fields
   \param size Amount of storage to allocate
@@ -229,21 +228,21 @@
 /*!
   \brief Set a field to a simple string value
   \param x Pointer to a structure containing fields
-  \param index Index position of the field within the structure
+  \param ptr Pointer to a field within the structure
   \param data String value to be copied into the field
   \return nothing
 */
 
-#define ast_string_field_index_set(x, index, data) do { 		\
-	const char *__d__ = (data);					\
-	size_t __dlen__ = (__d__) ? strlen(__d__) : 0;				\
-	const char **__p__ = (const char **)&((x)->__field_mgr_pool) + 1 + index;	\
-	if (__dlen__ == 0)							\
-		*__p__ = __ast_string_field_empty;				\
-	else if (__dlen__ <= strlen(*__p__))					\
-		strcpy((char *)*__p__, __d__);					\
+#define ast_string_field_ptr_set(x, ptr, data) do { 		\
+	const char *__d__ = (data);				\
+	size_t __dlen__ = (__d__) ? strlen(__d__) : 0;		\
+	const char **__p__ = (const char **)(ptr);		\
+	if (__dlen__ == 0)					\
+		*__p__ = __ast_string_field_empty;		\
+	else if (__dlen__ <= strlen(*__p__))			\
+		strcpy((char *)*__p__, __d__);			\
 	else if ( (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__ + 1) ) )	\
-		strcpy((char *)*__p__, __d__);					\
+		strcpy((char *)*__p__, __d__);			\
 	} while (0)
 
 /*!
@@ -253,34 +252,33 @@
   \param data String value to be copied into the field
   \return nothing
 */
-#define ast_string_field_set(x, field, data)	do {	\
-	int index = ast_string_field_index(x, field);	\
-	ast_string_field_index_set(x, index, data);	\
+#define ast_string_field_set(x, field, data)	do {		\
+	ast_string_field_ptr_set(x, &(x)->field, data);		\
 	} while (0)
 
 
 /*!
   \brief Set a field to a complex (built) value
   \param x Pointer to a structure containing fields
-  \param index Index position of the field within the structure
+  \param ptr Pointer to a field within the structure
   \param fmt printf-style format string
   \param args Arguments for format string
   \return nothing
 */
-#define ast_string_field_index_build(x, index, fmt, args...) \
-	__ast_string_field_index_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, index, fmt, args)
+#define ast_string_field_ptr_build(x, ptr, fmt, args...) \
+	__ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args)
 
 /*!
   \brief Set a field to a complex (built) value with prebuilt va_lists.
   \param x Pointer to a structure containing fields
-  \param index Index position of the field within the structure
+  \param ptr Pointer to a field within the structure
   \param fmt printf-style format string
   \param args1 Arguments for format string in va_list format
   \param args2 a second copy of the va_list for the sake of bsd, with no va_list copy operation
   \return nothing
 */
-#define ast_string_field_index_build_va(x, index, fmt, args1, args2) \
-	__ast_string_field_index_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, index, fmt, args1, args2)
+#define ast_string_field_ptr_build_va(x, ptr, fmt, args1, args2) \
+	__ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, ptr, fmt, args1, args2)
 
 /*!
   \brief Set a field to a complex (built) value
@@ -291,7 +289,7 @@
   \return nothing
 */
 #define ast_string_field_build(x, field, fmt, args...) \
-	__ast_string_field_index_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, ast_string_field_index(x, field), fmt, args)
+	__ast_string_field_ptr_build(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args)
 
 /*!
   \brief Set a field to a complex (built) value
@@ -303,7 +301,7 @@
   \return nothing
 */
 #define ast_string_field_build_va(x, field, fmt, args1, args2) \
-	__ast_string_field_index_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, ast_string_field_index(x, field), fmt, args1, args2)
+	__ast_string_field_ptr_build_va(&(x)->__field_mgr, &(x)->__field_mgr_pool, &(x)->field, fmt, args1, args2)
 
 /*!
   \brief Free the stringfield storage pools attached to a structure
@@ -337,7 +335,6 @@
 	while ((struct ast_string_field_mgr *)__p__ != &(x)->__field_mgr) \
 		*__p__++ = __ast_string_field_empty;		\
 	(x)->__field_mgr.used = 0;				\
-	(x)->__field_mgr.space = (x)->__field_mgr.size;		\
 	} while(0)
 #endif
 

Modified: team/rizzo/video_v2/main/utils.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/main/utils.c?view=diff&rev=87742&r1=87741&r2=87742
==============================================================================
--- team/rizzo/video_v2/main/utils.c (original)
+++ team/rizzo/video_v2/main/utils.c Tue Oct 30 18:30:20 2007
@@ -1140,8 +1140,7 @@
  * stringfields support routines.
  */
 
-/*! \brief the empty string for stringfield */
-const char __ast_string_field_empty[] = "";
+const char __ast_string_field_empty[] = ""; /*!< the empty string */
 
 /*! \brief add a new block to the pool.
  * We can only allocate from the topmost pool, so the
@@ -1158,7 +1157,6 @@
 	pool->prev = *pool_head;
 	*pool_head = pool;
 	mgr->size = size;
-	mgr->space = size;
 	mgr->used = 0;
 
 	return 0;
@@ -1186,8 +1184,9 @@
 	struct ast_string_field_pool **pool_head, size_t needed)
 {
 	char *result = NULL;
-
-	if (__builtin_expect(needed > mgr->space, 0)) {
+	size_t space = mgr->size - mgr->used;
+
+	if (__builtin_expect(needed > space, 0)) {
 		size_t new_size = mgr->size * 2;
 
 		while (new_size < needed)
@@ -1199,23 +1198,24 @@
 
 	result = (*pool_head)->base + mgr->used;
 	mgr->used += needed;
-	mgr->space -= needed;
 	return result;
 }
 
-void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
+void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
 	struct ast_string_field_pool **pool_head,
-	int index, const char *format, va_list ap1, va_list ap2)
+	const ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
 {
 	size_t needed;
 	char *dst = (*pool_head)->base + mgr->used;
-	const char **p = (const char **)pool_head + 1;
-
-	needed = vsnprintf(dst, mgr->space, format, ap1) + 1;
+	const char **p = (const char **)ptr;
+	size_t space = mgr->size - mgr->used;
+
+	/* try to write using available space */
+	needed = vsnprintf(dst, space, format, ap1) + 1;
 
 	va_end(ap1);
 
-	if (needed > mgr->space) {
+	if (needed > space) {	/* if it fails, reallocate */
 		size_t new_size = mgr->size * 2;
 
 		while (new_size < needed)
@@ -1228,21 +1228,20 @@
 		vsprintf(dst, format, ap2);
 	}
 
-	p[index] = dst;
+	*p = dst;
 	mgr->used += needed;
-	mgr->space -= needed;
-}
-
-void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
+}
+
+void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
 	struct ast_string_field_pool **pool_head,
-	int index, const char *format, ...)
+	const ast_string_field *ptr, const char *format, ...)
 {
 	va_list ap1, ap2;
 
 	va_start(ap1, format);
 	va_start(ap2, format);		/* va_copy does not exist on FreeBSD */
 
-	__ast_string_field_index_build_va(mgr, pool_head, index, format, ap1, ap2);
+	__ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap1, ap2);
 
 	va_end(ap1);
 	va_end(ap2);




More information about the asterisk-commits mailing list