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 */
+ ast_string_field last_alloc; /*!< the last field allocated */
};
/*!
int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
ast_string_field *fields, int num_fields);
+/*!
+ \internal
+ \brief Attempt to 'grow' an already allocated field to a larger size
+ \param mgr Pointer to the pool manager structure
+ \param needed Amount of space needed for this field
+ \param fields Pointer to the first entry of the field array
+ \param index Index position of the field within the structure
+ \return 0 on success, non-zero on failure
+
+ This function will attempt to increase the amount of space allocated to
+ an existing field to the amount requested; this is only possible if the
+ field was the last field allocated from the current storage pool and
+ the pool has enough space available. If so, the additional space will be
+ allocated to this field and the field's address will not be changed.
+*/
+int __ast_string_field_index_grow(struct ast_string_field_mgr *mgr, size_t needed,
+ ast_string_field *fields, int index);
+
/*!
\internal
\brief Allocate space for a field
\return nothing
*/
void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
- ast_string_field *fields, int num_fields,
- int index, const char *format, va_list a1, va_list a2);
+ ast_string_field *fields, int num_fields,
+ int index, const char *format, va_list a1, va_list a2);
/*!
\brief Declare a string field
\return nothing
*/
#define ast_string_field_index_set(x, index, data) do { \
- char *__zz__ = (char*)(x)->__begin_field[index]; \
- size_t __dlen__ = strlen(data); \
- if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
+ char *__zz__ = (char*) (x)->__begin_field[index]; \
+ size_t __dlen__ = strlen(data) + 1; \
+ if ( __dlen__ == 1 ) {\
+ (x)->__begin_field[index] = __ast_string_field_empty; \
} else { \
- if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
- strcpy(__zz__, data); \
- } else { \
- if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
- strcpy((char*)(x)->__begin_field[index], data); \
- } \
- } \
+ if (!__ast_string_field_index_grow(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], index)) { \
+ memcpy(__zz__, data, __dlen__); \
+ } else { \
+ if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) \
+ memcpy((char*) (x)->__begin_field[index], data, __dlen__); \
+ } \
+ } \
} while (0)
-#ifdef FOR_TEST
#define ast_string_field_index_logset(x, index, data, logstr) do { \
- char *__zz__ = (char*)(x)->__begin_field[index]; \
- size_t __dlen__ = strlen(data); \
- if( __dlen__ == 0 ) { (x)->__begin_field[index] = __ast_string_field_empty; \
+ char *__zz__ = (char*) (x)->__begin_field[index]; \
+ size_t __dlen__ = strlen(data) + 1; \
+ if ( __dlen__ == 1 ) {\
+ (x)->__begin_field[index] = __ast_string_field_empty; \
} else { \
- if( __zz__[0] != 0 && __dlen__ <= strlen(__zz__) ) { \
- ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
- strcpy(__zz__, data); \
- } else { \
- ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
- if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__ + 1, &(x)->__begin_field[0], ast_string_field_count(x)))) \
- strcpy((char*)(x)->__begin_field[index], data); \
- } \
- } \
+ if (!__ast_string_field_index_grow(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], index)) { \
+ ast_verbose("%s: ======replacing '%s' with '%s'\n", logstr, __zz__, data); \
+ memcpy(__zz__, data, __dlen__); \
+ } else { \
+ if (((x)->__begin_field[index] = __ast_string_field_alloc_space(&(x)->__field_mgr, __dlen__, &(x)->__begin_field[0], ast_string_field_count(x)))) \
+ ast_verbose("%s: ++++++allocating room for '%s' to replace '%s'\n", logstr, data, __zz__); \
+ memcpy((char*) (x)->__begin_field[index], data, __dlen__); \
+ } \
+ } \
} while (0)
-#endif
/*!
\brief Set a field to a simple string value
#define ast_string_field_set(x, field, data) \
ast_string_field_index_set(x, ast_string_field_index(x, field), data)
-#ifdef FOR_TEST
#define ast_string_field_logset(x, field, data, logstr) \
ast_string_field_index_logset(x, ast_string_field_index(x, field), data, logstr)
-#endif
/*!
\brief Set a field to a complex (built) value
mgr->size = size;
mgr->space = size;
mgr->used = 0;
+ mgr->last_alloc = NULL;
return 0;
}
result = mgr->pool->base + mgr->used;
mgr->used += needed;
mgr->space -= needed;
+ mgr->last_alloc = result;
return result;
}
+int __ast_string_field_index_grow(struct ast_string_field_mgr *mgr, size_t needed,
+ ast_string_field *fields, int index)
+{
+ int grow = needed - (strlen(fields[index]) + 1);
+
+ if (grow <= 0) {
+ return 0;
+ }
+
+ if (fields[index] != mgr->last_alloc) {
+ return 1;
+ }
+
+ if (mgr->space < grow) {
+ return 1;
+ }
+
+ mgr->space -= grow;
+ mgr->used += grow;
+
+ return 0;
+}
+
void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
- ast_string_field *fields, int num_fields,
- int index, const char *format, va_list ap1, va_list ap2)
+ ast_string_field *fields, int num_fields,
+ int index, const char *format, va_list ap1, va_list ap2)
{
size_t needed;
}
fields[index] = mgr->pool->base + mgr->used;
+ mgr->last_alloc = fields[index];
mgr->used += needed;
mgr->space -= needed;
}