*buffer->current++ = ch;
}
+/* Calculate the result size of expanded char array in %ms, %mS, %m[
+ or %lm[. OLDSIZE is current allocation size and NEED is the
+ remaining field-width budget (chars still to read) or negative if
+ unbounded. */
+static __always_inline size_t
+grow_to_fit (size_t oldsize, int need)
+{
+ if (need < 0 || oldsize < need)
+ return oldsize * 2;
+ /* oldsize >= need: grow requested capacity and 1 byte for `\0' */
+ return oldsize + need + 1;
+}
+
/* Read formatted input from S according to the format string
FORMAT, using the argument list in ARG.
Return the number of assignments made, or -1 for an input error. */
&& *strptr + strsize - str <= MB_LEN_MAX)
{
/* We have to enlarge the buffer if the `m' flag
- was given. */
+ was given. And we may not expand str by width
+ as the wcrtomb may return various bytes. */
size_t strleng = str - *strptr;
char *newstr;
&& *strptr + strsize - str <= MB_LEN_MAX)
{
/* We have to enlarge the buffer if the `a' or `m'
- flag was given. */
+ flag was given. And we may not expand str by
+ width as the wcrtomb may return various bytes. */
size_t strleng = str - *strptr;
char *newstr;
&& (char *) str == *strptr + strsize)
{
/* Enlarge the buffer. */
- str = (char *) realloc (*strptr, 2 * strsize);
+ size_t newsize = grow_to_fit (strsize, width);
+
+ str = (char *) realloc (*strptr, newsize);
if (str == NULL)
{
/* Can't allocate that much. Last-ditch
{
*strptr = (char *) str;
str += strsize;
- strsize *= 2;
+ strsize = newsize;
}
}
}
&& wstr == (wchar_t *) *strptr + strsize)
{
/* Enlarge the buffer. */
- wstr = (wchar_t *) realloc (*strptr,
- (2 * strsize)
- * sizeof (wchar_t));
+ size_t newsize = grow_to_fit (strsize, width);
+
+ wstr = (wchar_t *) realloc (
+ *strptr, newsize * sizeof (wchar_t));
if (wstr == NULL)
{
/* Can't allocate that much. Last-ditch
{
*strptr = (char *) wstr;
wstr += strsize;
- strsize *= 2;
+ strsize = newsize;
}
}
}
&& wstr == (wchar_t *) *strptr + strsize)
{
/* Enlarge the buffer. */
+ size_t newsize = grow_to_fit (strsize, width);
+
wstr = (wchar_t *) realloc (*strptr,
- (2 * strsize
- * sizeof (wchar_t)));
+ newsize * sizeof (wchar_t));
if (wstr == NULL)
{
/* Can't allocate that much. Last-ditch effort. */
{
*strptr = (char *) wstr;
wstr += strsize;
- strsize *= 2;
+ strsize = newsize;
}
}
}
&& wstr == (wchar_t *) *strptr + strsize)
{
/* Enlarge the buffer. */
- wstr = (wchar_t *) realloc (*strptr,
- (2 * strsize)
- * sizeof (wchar_t));
+ size_t newsize = grow_to_fit (strsize, width);
+
+ wstr = (wchar_t *) realloc (
+ *strptr, newsize * sizeof (wchar_t));
if (wstr == NULL)
{
/* Can't allocate that much. Last-ditch
{
*strptr = (char *) wstr;
wstr += strsize;
- strsize *= 2;
+ strsize = newsize;
}
}
}
&& wstr == (wchar_t *) *strptr + strsize)
{
/* Enlarge the buffer. */
- wstr = (wchar_t *) realloc (*strptr,
- (2 * strsize
- * sizeof (wchar_t)));
+ size_t newsize = grow_to_fit (strsize, width);
+
+ wstr = (wchar_t *) realloc (
+ *strptr, newsize * sizeof (wchar_t));
if (wstr == NULL)
{
/* Can't allocate that much. Last-ditch
{
*strptr = (char *) wstr;
wstr += strsize;
- strsize *= 2;
+ strsize = newsize;
}
}
}
if ((flags & MALLOC)
&& *strptr + strsize - str <= MB_LEN_MAX)
{
- /* Enlarge the buffer. */
+ /* Enlarge the buffer. And we may not
+ expand str by width as the wcrtomb may
+ return various bytes. */
size_t strleng = str - *strptr;
char *newstr;
&& (char *) str == *strptr + strsize)
{
/* Enlarge the buffer. */
- size_t newsize = 2 * strsize;
+ size_t newsize = grow_to_fit (strsize, width);
allocagain:
str = (char *) realloc (*strptr, newsize);