summaryrefslogtreecommitdiff
path: root/lib/printf-parse.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-02-04 19:22:43 +0100
committerBruno Haible <bruno@clisp.org>2011-02-04 19:22:43 +0100
commit8c6ae0f8ac5b35f5237375dfe748300544711701 (patch)
tree015202934c1905796185ec1eefff89020454544a /lib/printf-parse.c
parentb6b8999acb7d09d22a2ea4809ec4de041d761f05 (diff)
downloadgnulib-8c6ae0f8ac5b35f5237375dfe748300544711701.tar.gz
vasnprintf: Reduce use of malloc for small format strings.
* lib/printf-args.h (N_DIRECT_ALLOC_ARGUMENTS): New macro. (arguments): Add room for the first 7 arguments. * lib/printf-parse.h (N_DIRECT_ALLOC_DIRECTIVES): New macro. (char_directives, u8_directives, u16_directives, u32_directives): Add room for the first 7 directives. * lib/printf-parse.c: Include <string.h>. (PRINTF_PARSE): Change memory handling code so that it uses the first 7 preallocated elements in an 'arguments' or 'DIRECTIVES' struct. * lib/vasnprintf.c (VASNPRINTF): Update memory handling code. Reported by Pádraig Brady <P@draigbrady.com>.
Diffstat (limited to 'lib/printf-parse.c')
-rw-r--r--lib/printf-parse.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/lib/printf-parse.c b/lib/printf-parse.c
index e44a8b2321..c4e1d37bf5 100644
--- a/lib/printf-parse.c
+++ b/lib/printf-parse.c
@@ -63,6 +63,9 @@
/* malloc(), realloc(), free(). */
#include <stdlib.h>
+/* memcpy(). */
+#include <string.h>
+
/* errno. */
#include <errno.h>
@@ -80,23 +83,20 @@ STATIC
int
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
{
- const CHAR_T *cp = format; /* pointer into format */
+ const CHAR_T *cp = format; /* pointer into format */
size_t arg_posn = 0; /* number of regular arguments consumed */
- size_t d_allocated; /* allocated elements of d->dir */
- size_t a_allocated; /* allocated elements of a->arg */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
size_t max_width_length = 0;
size_t max_precision_length = 0;
d->count = 0;
- d_allocated = 1;
- d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
- if (d->dir == NULL)
- /* Out of memory. */
- goto out_of_memory_1;
+ d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
+ d->dir = d->direct_alloc_dir;
a->count = 0;
- a_allocated = 0;
- a->arg = NULL;
+ a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
+ a->arg = a->direct_alloc_arg;
#define REGISTER_ARG(_index_,_type_) \
{ \
@@ -113,12 +113,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
if (size_overflow_p (memory_size)) \
/* Overflow, would lead to out of memory. */ \
goto out_of_memory; \
- memory = (argument *) (a->arg \
+ memory = (argument *) (a->arg != a->direct_alloc_arg \
? realloc (a->arg, memory_size) \
: malloc (memory_size)); \
if (memory == NULL) \
/* Out of memory. */ \
goto out_of_memory; \
+ if (a->arg == a->direct_alloc_arg) \
+ memcpy (memory, a->arg, a->count * sizeof (argument)); \
a->arg = memory; \
} \
while (a->count <= n) \
@@ -588,10 +590,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
if (size_overflow_p (memory_size))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
- memory = (DIRECTIVE *) realloc (d->dir, memory_size);
+ memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
+ ? realloc (d->dir, memory_size)
+ : malloc (memory_size));
if (memory == NULL)
/* Out of memory. */
goto out_of_memory;
+ if (d->dir == d->direct_alloc_dir)
+ memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
d->dir = memory;
}
}
@@ -610,19 +616,18 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
return 0;
error:
- if (a->arg)
+ if (a->arg != a->direct_alloc_arg)
free (a->arg);
- if (d->dir)
+ if (d->dir != d->direct_alloc_dir)
free (d->dir);
errno = EINVAL;
return -1;
out_of_memory:
- if (a->arg)
+ if (a->arg != a->direct_alloc_arg)
free (a->arg);
- if (d->dir)
+ if (d->dir != d->direct_alloc_dir)
free (d->dir);
-out_of_memory_1:
errno = ENOMEM;
return -1;
}