vfscanf: Implement struct char_buffer with a dynamic array

Message ID 20170602120011.693C5400EA94D@oldenburg.str.redhat.com
State New, archived
Headers

Commit Message

Florian Weimer June 2, 2017, noon UTC
  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.
  

Patch

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;