This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] vfscanf: Implement struct char_buffer with a dynamic array
- From: fweimer at redhat dot com (Florian Weimer)
- To: libc-alpha at sourceware dot org
- Date: Fri, 02 Jun 2017 14:00:11 +0200
- Subject: [PATCH] vfscanf: Implement struct char_buffer with a dynamic array
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6F3FD142A79
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6F3FD142A79
2017-06-02 Florian Weimer <fweimer@redhat.com>
* stdio-common/vfscanf.c (struct char_buffer): Define using
<malloc/dynarray.h>.
(_IO_vfscanf_internal): Adjust to dynarray-based struct
char_buffer.
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 1adf27e..093d17c 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -30,7 +30,6 @@
#include <libc-diag.h>
#include <libc-lock.h>
#include <locale/localeinfo.h>
-#include <scratch_buffer.h>
#ifdef __GNUC__
# define HAVE_LONGLONG
@@ -187,6 +186,7 @@
_IO_funlockfile (S); \
__libc_cleanup_region_end (0)
+
struct ptrs_to_free
{
size_t count;
@@ -194,77 +194,14 @@ struct ptrs_to_free
char **ptrs[32];
};
-struct char_buffer {
- CHAR_T *current;
- CHAR_T *end;
- struct scratch_buffer scratch;
-};
-
-/* Returns a pointer to the first CHAR_T object in the buffer. Only
- valid if char_buffer_add (BUFFER, CH) has been called and
- char_buffer_error (BUFFER) is false. */
-static inline CHAR_T *
-char_buffer_start (const struct char_buffer *buffer)
-{
- return (CHAR_T *) buffer->scratch.data;
-}
-
-/* Returns the number of CHAR_T objects in the buffer. Only valid if
- char_buffer_error (BUFFER) is false. */
-static inline size_t
-char_buffer_size (const struct char_buffer *buffer)
-{
- return buffer->current - char_buffer_start (buffer);
-}
-
-/* Reinitializes BUFFER->current and BUFFER->end to cover the entire
- scratch buffer. */
-static inline void
-char_buffer_rewind (struct char_buffer *buffer)
-{
- buffer->current = char_buffer_start (buffer);
- buffer->end = buffer->current + buffer->scratch.length / sizeof (CHAR_T);
-}
-
-/* Returns true if a previous call to char_buffer_add (BUFFER, CH)
- failed. */
-static inline bool
-char_buffer_error (const struct char_buffer *buffer)
-{
- return __glibc_unlikely (buffer->current == NULL);
-}
-
-/* Slow path for char_buffer_add. */
-static void
-char_buffer_add_slow (struct char_buffer *buffer, CHAR_T ch)
-{
- if (char_buffer_error (buffer))
- return;
- size_t offset = buffer->end - (CHAR_T *) buffer->scratch.data;
- if (!scratch_buffer_grow_preserve (&buffer->scratch))
- {
- buffer->current = NULL;
- buffer->end = NULL;
- return;
- }
- char_buffer_rewind (buffer);
- buffer->current += offset;
- *buffer->current++ = ch;
-}
-
-/* Adds CH to BUFFER. This function does not report any errors, check
- for them with char_buffer_error. */
-static inline void
-char_buffer_add (struct char_buffer *buffer, CHAR_T ch)
- __attribute__ ((always_inline));
-static inline void
-char_buffer_add (struct char_buffer *buffer, CHAR_T ch)
-{
- if (__glibc_unlikely (buffer->current == buffer->end))
- char_buffer_add_slow (buffer, ch);
- else
- *buffer->current++ = ch;
-}
+#define DYNARRAY_STRUCT char_buffer
+#define DYNARRAY_ELEMENT CHAR_T
+#define DYNARRAY_PREFIX char_buffer_
+#ifndef COMPILE_WSCANF
+/* We need 256 array elements for processing %[...] specifiers. */
+# define DYNARRAY_INITIAL_SIZE 256
+#endif
+#include <malloc/dynarray-skeleton.c>
/* Read formatted input from S according to the format string
FORMAT, using the argument list in ARG.
@@ -337,7 +274,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Workspace. */
CHAR_T *tw; /* Temporary pointer. */
struct char_buffer charbuf;
- scratch_buffer_init (&charbuf.scratch);
+ char_buffer_init (&charbuf);
#ifdef __va_copy
__va_copy (arg, argptr);
@@ -485,7 +422,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
argpos = 0;
/* Prepare temporary buffer. */
- char_buffer_rewind (&charbuf);
+ char_buffer_clear (&charbuf);
/* Check for a positional parameter specification. */
if (ISDIGIT ((UCHAR_T) *f))
@@ -1692,7 +1629,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
}
}
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -1704,7 +1641,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* We are pushing all read characters back. */
if (cmpp > thousands)
{
- charbuf.current -= cmpp - thousands;
+ char_buffer_resize
+ (&charbuf,
+ char_buffer_size (&charbuf) - (cmpp - thousands));
ungetc (c, s);
while (--cmpp > thousands)
ungetc_not_eof ((unsigned char) *cmpp, s);
@@ -1718,7 +1657,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* The last thousands character will be added back by
the char_buffer_add below. */
- --charbuf.current;
+ char_buffer_remove_last (&charbuf);
#endif
}
else
@@ -1765,7 +1704,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
}
}
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -1777,7 +1716,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* We are pushing all read characters back. */
if (cmpp > thousands)
{
- charbuf.current -= cmpp - thousands;
+ char_buffer_resize
+ (&charbuf,
+ char_buffer_size (&charbuf) - (cmpp - thousands));
ungetc (c, s);
while (--cmpp > thousands)
ungetc_not_eof ((unsigned char) *cmpp, s);
@@ -1791,7 +1732,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* The last thousands character will be added back by
the char_buffer_add below. */
- --charbuf.current;
+ char_buffer_remove_last (&charbuf);
#endif
}
else
@@ -1804,7 +1745,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
c = inchar ();
}
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -1813,8 +1754,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (char_buffer_size (&charbuf) == 0
|| (char_buffer_size (&charbuf) == 1
- && (char_buffer_start (&charbuf)[0] == L_('+')
- || char_buffer_start (&charbuf)[0] == L_('-'))))
+ && (*char_buffer_at (&charbuf, 0) == L_('+')
+ || *char_buffer_at (&charbuf, 0) == L_('-'))))
{
/* There was no number. If we are supposed to read a pointer
we must recognize "(nil)" as well. */
@@ -1844,7 +1785,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Convert the number. */
char_buffer_add (&charbuf, L_('\0'));
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -1854,21 +1795,21 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
if (flags & NUMBER_SIGNED)
num.q = __strtoll_internal
- (char_buffer_start (&charbuf), &tw, base, flags & GROUP);
+ (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP);
else
num.uq = __strtoull_internal
- (char_buffer_start (&charbuf), &tw, base, flags & GROUP);
+ (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP);
}
else
{
if (flags & NUMBER_SIGNED)
num.l = __strtol_internal
- (char_buffer_start (&charbuf), &tw, base, flags & GROUP);
+ (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP);
else
num.ul = __strtoul_internal
- (char_buffer_start (&charbuf), &tw, base, flags & GROUP);
+ (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP);
}
- if (__glibc_unlikely (char_buffer_start (&charbuf) == tw))
+ if (__glibc_unlikely (char_buffer_at (&charbuf, 0) == tw))
conv_error ();
if (!(flags & SUPPRESS))
@@ -2045,7 +1986,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
while (1)
{
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -2061,7 +2002,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
char_buffer_add (&charbuf, c);
got_digit = 1;
}
- else if (got_e && charbuf.current[-1] == exp_char
+ else if (got_e
+ && *char_buffer_at (&charbuf,
+ char_buffer_size (&charbuf) - 1)
+ == exp_char
&& (c == L_('-') || c == L_('+')))
char_buffer_add (&charbuf, c);
else if (got_digit && !got_e
@@ -2167,7 +2111,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
--width;
}
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -2279,13 +2223,16 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
conversion is done correctly. */
while (1)
{
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
goto errout;
}
- if (got_e && charbuf.current[-1] == exp_char
+ if (got_e
+ && *char_buffer_at (&charbuf,
+ char_buffer_size (&charbuf) - 1)
+ == exp_char
&& (c == L_('-') || c == L_('+')))
char_buffer_add (&charbuf, c);
else if (char_buffer_size (&charbuf) > 0 && !got_e
@@ -2402,7 +2349,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#endif
}
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -2420,7 +2367,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
scan_float:
/* Convert the number. */
char_buffer_add (&charbuf, L_('\0'));
- if (char_buffer_error (&charbuf))
+ if (char_buffer_has_failed (&charbuf))
{
__set_errno (ENOMEM);
done = EOF;
@@ -2429,26 +2376,26 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if ((flags & LONGDBL) && !__ldbl_is_dbl)
{
long double d = __strtold_internal
- (char_buffer_start (&charbuf), &tw, flags & GROUP);
- if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
+ (char_buffer_at (&charbuf, 0), &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0))
*ARG (long double *) = negative ? -d : d;
}
else if (flags & (LONG | LONGDBL))
{
double d = __strtod_internal
- (char_buffer_start (&charbuf), &tw, flags & GROUP);
- if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
+ (char_buffer_at (&charbuf, 0), &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0))
*ARG (double *) = negative ? -d : d;
}
else
{
float d = __strtof_internal
- (char_buffer_start (&charbuf), &tw, flags & GROUP);
- if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
+ (char_buffer_at (&charbuf, 0), &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0))
*ARG (float *) = negative ? -d : d;
}
- if (__glibc_unlikely (tw == char_buffer_start (&charbuf)))
+ if (__glibc_unlikely (tw == char_buffer_at (&charbuf, 0)))
conv_error ();
if (!(flags & SUPPRESS))
@@ -2494,13 +2441,12 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#else
/* Fill WP with byte flags indexed by character.
We will use this flag map for matching input characters. */
- if (!scratch_buffer_set_array_size
- (&charbuf.scratch, UCHAR_MAX + 1, 1))
+ if (!char_buffer_resize (&charbuf, UCHAR_MAX + 1))
{
done = EOF;
goto errout;
}
- memset (charbuf.scratch.data, '\0', UCHAR_MAX + 1);
+ memset (char_buffer_at (&charbuf, 0), '\0', UCHAR_MAX + 1);
fc = *f;
if (fc == ']' || fc == '-')
@@ -2508,7 +2454,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* If ] or - appears before any char in the set, it is not
the terminator or separator, but the first char in the
set. */
- ((char *)charbuf.scratch.data)[fc] = 1;
+ *char_buffer_at (&charbuf, fc) = 1;
++f;
}
@@ -2519,11 +2465,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Add all characters from the one before the '-'
up to (but not including) the next format char. */
for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
- ((char *)charbuf.scratch.data)[fc] = 1;
+ *char_buffer_at (&charbuf, fc) = 1;
}
else
/* Add the character to the flag map. */
- ((char *)charbuf.scratch.data)[fc] = 1;
+ *char_buffer_at (&charbuf, fc) = 1;
if (__glibc_unlikely (fc == '\0'))
conv_error();
@@ -2652,7 +2598,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
do
{
- if (((char *) charbuf.scratch.data)[c] == not_in)
+ if (*char_buffer_at (&charbuf, c) == not_in)
{
ungetc_not_eof (c, s);
break;
@@ -2880,7 +2826,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#else
do
{
- if (((char *) charbuf.scratch.data)[c] == not_in)
+ if (*char_buffer_at (&charbuf, c) == not_in)
{
ungetc_not_eof (c, s);
break;
@@ -3020,7 +2966,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Unlock stream. */
UNLOCK_STREAM (s);
- scratch_buffer_free (&charbuf.scratch);
+ char_buffer_free (&charbuf);
if (errp != NULL)
*errp |= errval;