Mercurial > hg > octave-kai > gnulib-hg
comparison lib/xvasprintf.c @ 6779:1807d27bf1ec
Recognize the special case of a string concatenation in xvasprintf.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Tue, 09 May 2006 17:26:15 +0000 |
parents | a48fb0e98c8c |
children | 6c0cb059c9ea |
comparison
equal
deleted
inserted
replaced
6778:3f44368390a2 | 6779:1807d27bf1ec |
---|---|
1 /* vasprintf and asprintf with out-of-memory checking. | 1 /* vasprintf and asprintf with out-of-memory checking. |
2 Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc. | 2 Copyright (C) 1999, 2002-2004, 2006 Free Software Foundation, Inc. |
3 | 3 |
4 This program is free software; you can redistribute it and/or modify | 4 This program is free software; you can redistribute it and/or modify |
5 it under the terms of the GNU General Public License as published by | 5 it under the terms of the GNU General Public License as published by |
6 the Free Software Foundation; either version 2, or (at your option) | 6 the Free Software Foundation; either version 2, or (at your option) |
7 any later version. | 7 any later version. |
21 | 21 |
22 /* Specification. */ | 22 /* Specification. */ |
23 #include "xvasprintf.h" | 23 #include "xvasprintf.h" |
24 | 24 |
25 #include <errno.h> | 25 #include <errno.h> |
26 #include <limits.h> | |
27 #include <string.h> | |
26 | 28 |
27 #include "vasprintf.h" | 29 #include "vasprintf.h" |
28 #include "xalloc.h" | 30 #include "xalloc.h" |
31 | |
32 /* Checked size_t computations. */ | |
33 #include "xsize.h" | |
34 | |
35 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ | |
36 #ifndef EOVERFLOW | |
37 # define EOVERFLOW E2BIG | |
38 #endif | |
39 | |
40 static inline char * | |
41 xstrcat (size_t argcount, va_list args) | |
42 { | |
43 char *result; | |
44 va_list ap; | |
45 size_t totalsize; | |
46 size_t i; | |
47 char *p; | |
48 | |
49 /* Determine the total size. */ | |
50 totalsize = 0; | |
51 va_copy (ap, args); | |
52 for (i = argcount; i > 0; i--) | |
53 { | |
54 const char *next = va_arg (ap, const char *); | |
55 totalsize = xsum (totalsize, strlen (next)); | |
56 } | |
57 va_end (ap); | |
58 | |
59 /* Test for overflow in the summing pass above or in (totalsize + 1) below. | |
60 Also, don't return a string longer than INT_MAX, for consistency with | |
61 vasprintf(). */ | |
62 if (totalsize == SIZE_MAX || totalsize > INT_MAX) | |
63 { | |
64 errno = EOVERFLOW; | |
65 return NULL; | |
66 } | |
67 | |
68 /* Allocate and fill the result string. */ | |
69 result = (char *) xmalloc (totalsize + 1); | |
70 p = result; | |
71 for (i = argcount; i > 0; i--) | |
72 { | |
73 const char *next = va_arg (args, const char *); | |
74 size_t len = strlen (next); | |
75 memcpy (p, next, len); | |
76 p += len; | |
77 } | |
78 *p = '\0'; | |
79 | |
80 return result; | |
81 } | |
29 | 82 |
30 char * | 83 char * |
31 xvasprintf (const char *format, va_list args) | 84 xvasprintf (const char *format, va_list args) |
32 { | 85 { |
33 char *result; | 86 char *result; |
87 | |
88 /* Recognize the special case format = "%s...%s". It is a frequently used | |
89 idiom for string concatenation and needs to be fast. We don't want to | |
90 have a separate function xstrcat() for this purpose. */ | |
91 { | |
92 size_t argcount = 0; | |
93 const char *f; | |
94 | |
95 for (f = format;;) | |
96 { | |
97 if (*f == '\0') | |
98 /* Recognized the special case of string concatenation. */ | |
99 return xstrcat (argcount, args); | |
100 if (*f != '%') | |
101 break; | |
102 f++; | |
103 if (*f != 's') | |
104 break; | |
105 f++; | |
106 argcount++; | |
107 } | |
108 } | |
34 | 109 |
35 if (vasprintf (&result, format, args) < 0) | 110 if (vasprintf (&result, format, args) < 0) |
36 { | 111 { |
37 if (errno == ENOMEM) | 112 if (errno == ENOMEM) |
38 xalloc_die (); | 113 xalloc_die (); |