bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-gnulib] readtokens merge from coreutils


From: Paul Eggert
Subject: [Bug-gnulib] readtokens merge from coreutils
Date: Tue, 30 Mar 2004 23:36:14 -0800
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed this:

2004-03-30  Jim Meyering  <address@hidden>

        * readtokens.c (readtoken): Don't leak 64 bytes when reading
        an empty input stream.

        * readtokens.c: Include <stdbool.h>.
        (readtoken): Use `size_t' rather than int/long.
        All callers adjusted.
        Use `bool' rather than `int' where appropriate.
        Use memset rather than an explicit loop.
        Use x2nrealloc rather than xrealloc.
        Allow the use of `\0' as a delimiter.
        (readtokens): Likewise.
        * readtokens.h (readtoken, readtokens): Update prototypes.

Index: lib/readtokens.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/readtokens.h,v
retrieving revision 1.5
diff -p -u -r1.5 readtokens.h
--- lib/readtokens.h    7 Jun 2003 10:30:19 -0000       1.5
+++ lib/readtokens.h    31 Mar 2004 07:32:09 -0000
@@ -1,6 +1,6 @@
 /* readtokens.h -- Functions for reading tokens from an input stream.
 
-   Copyright (C) 1990, 1991, 1999, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1999, 2001-2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -18,34 +18,26 @@
 
    Written by Jim Meyering. */
 
-#ifndef H_READTOKENS_H
-# define H_READTOKENS_H
+#ifndef READTOKENS_H
+# define READTOKENS_H
 
 # include <stdio.h>
 
-# ifndef INITIAL_TOKEN_LENGTH
-#  define INITIAL_TOKEN_LENGTH 20
-# endif
-
-# ifndef TOKENBUFFER_DEFINED
-#  define TOKENBUFFER_DEFINED
 struct tokenbuffer
 {
-  long size;
+  size_t size;
   char *buffer;
 };
 typedef struct tokenbuffer token_buffer;
 
-# endif /* not TOKENBUFFER_DEFINED */
-
 void init_tokenbuffer (token_buffer *tokenbuffer);
 
-long
-  readtoken (FILE *stream, const char *delim, int n_delim,
+size_t
+  readtoken (FILE *stream, const char *delim, size_t n_delim,
             token_buffer *tokenbuffer);
-int
-  readtokens (FILE *stream, int projected_n_tokens,
-             const char *delim, int n_delim,
-             char ***tokens_out, long **token_lengths);
+size_t
+  readtokens (FILE *stream, size_t projected_n_tokens,
+             const char *delim, size_t n_delim,
+             char ***tokens_out, size_t **token_lengths);
 
-#endif /* not H_READTOKENS_H */
+#endif /* not READTOKENS_H */
Index: lib/readtokens.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/readtokens.c,v
retrieving revision 1.12
diff -p -u -r1.12 readtokens.c
--- lib/readtokens.c    10 Sep 2003 04:25:35 -0000      1.12
+++ lib/readtokens.c    31 Mar 2004 07:32:09 -0000
@@ -1,5 +1,5 @@
 /* readtokens.c  -- Functions for reading tokens from an input stream.
-   Copyright (C) 1990-1991, 1999, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1990-1991, 1999-2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -19,13 +19,7 @@
 
 /* This almost supercedes xreadline stuff -- using delim="\n"
    gives the same functionality, except that these functions
-   would never return empty lines.
-
-   To Do:
-     - To allow '\0' as a delimiter, I will have to change
-       interfaces to permit specification of delimiter-string
-       length.
-   */
+   would never return empty lines. */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -36,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include "unlocked-io.h"
 #include "xalloc.h"
@@ -48,45 +43,48 @@
 void
 init_tokenbuffer (token_buffer *tokenbuffer)
 {
-  tokenbuffer->size = INITIAL_TOKEN_LENGTH;
-  tokenbuffer->buffer = xmalloc (INITIAL_TOKEN_LENGTH);
+  tokenbuffer->size = 0;
+  tokenbuffer->buffer = NULL;
 }
 
-/* Read a token from `stream' into `tokenbuffer'.
+/* Read a token from STREAM into TOKENBUFFER.
+   A token is delimited by any of the N_DELIM bytes in DELIM.
    Upon return, the token is in tokenbuffer->buffer and
-   has a trailing '\0' instead of the original delimiter.
+   has a trailing '\0' instead of any original delimiter.
    The function value is the length of the token not including
-   the final '\0'.  When EOF is reached (i.e. on the call
-   after the last token is read), -1 is returned and tokenbuffer
-   isn't modified.
+   the final '\0'.  Upon EOF (i.e. on the call after the last
+   token is read) or error, return -1 without modifying tokenbuffer.
+   The EOF and error conditions may be distinguished in the caller
+   by testing ferror (STREAM).
 
-   This function will work properly on lines containing NUL bytes
-   and on files that aren't newline-terminated.  */
+   This function works properly on lines containing NUL bytes
+   and on files do not end with a delimiter.  */
 
-long
+size_t
 readtoken (FILE *stream,
           const char *delim,
-          int n_delim,
+          size_t n_delim,
           token_buffer *tokenbuffer)
 {
   char *p;
-  int c, i, n;
+  int c;
+  size_t i, n;
   static const char *saved_delim = NULL;
   static char isdelim[256];
-  int same_delimiters;
+  bool same_delimiters;
 
   if (delim == NULL && saved_delim == NULL)
     abort ();
 
-  same_delimiters = 0;
+  same_delimiters = false;
   if (delim != saved_delim && saved_delim != NULL)
     {
-      same_delimiters = 1;
+      same_delimiters = true;
       for (i = 0; i < n_delim; i++)
        {
          if (delim[i] != saved_delim[i])
            {
-             same_delimiters = 0;
+             same_delimiters = false;
              break;
            }
        }
@@ -94,37 +92,33 @@ readtoken (FILE *stream,
 
   if (!same_delimiters)
     {
-      const char *t;
-      unsigned int j;
+      size_t j;
       saved_delim = delim;
-      for (j = 0; j < sizeof (isdelim); j++)
-       isdelim[j] = 0;
-      for (t = delim; *t; t++)
-       isdelim[(unsigned char) *t] = 1;
+      memset (isdelim, 0, sizeof isdelim);
+      for (j = 0; j < n_delim; j++)
+       isdelim[(unsigned char) delim[j]] = 1;
     }
 
-  p = tokenbuffer->buffer;
-  n = tokenbuffer->size;
-  i = 0;
-
-  /* FIXME: don't fool with this caching BS.  Use strchr instead.  */
+  /* FIXME: don't fool with this caching.  Use strchr instead.  */
   /* skip over any leading delimiters */
   for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream))
     {
       /* empty */
     }
 
+  p = tokenbuffer->buffer;
+  n = tokenbuffer->size;
+  i = 0;
   for (;;)
     {
-      if (i >= n)
-       {
-         n = 3 * (n / 2 + 1);
-         p = xrealloc (p, (unsigned int) n);
-       }
+      if (c < 0 && i == 0)
+       return -1;
+
+      if (i == n)
+       p = x2nrealloc (p, &n, sizeof *p);
+
       if (c < 0)
        {
-         if (i == 0)
-           return (-1);
          p[i] = 0;
          break;
        }
@@ -139,64 +133,61 @@ readtoken (FILE *stream,
 
   tokenbuffer->buffer = p;
   tokenbuffer->size = n;
-  return (i);
+  return i;
 }
 
-/* Return a NULL-terminated array of pointers to tokens
-   read from `stream.'  The number of tokens is returned
-   as the value of the function.
-   All storage is obtained through calls to malloc();
+/* Build a NULL-terminated array of pointers to tokens
+   read from STREAM.  Return the number of tokens read.
+   All storage is obtained through calls to xmalloc-like functions.
 
    %%% Question: is it worth it to do a single
    %%% realloc() of `tokens' just before returning? */
 
-int
+size_t
 readtokens (FILE *stream,
-           int projected_n_tokens,
+           size_t projected_n_tokens,
            const char *delim,
-           int n_delim,
+           size_t n_delim,
            char ***tokens_out,
-           long **token_lengths)
+           size_t **token_lengths)
 {
   token_buffer tb, *token = &tb;
-  int token_length;
   char **tokens;
-  long *lengths;
-  int sz;
-  int n_tokens;
+  size_t *lengths;
+  size_t sz;
+  size_t n_tokens;
 
-  n_tokens = 0;
-  if (projected_n_tokens > 0)
-    projected_n_tokens++;      /* add one for trailing NULL pointer */
-  else
+  if (projected_n_tokens == 0)
     projected_n_tokens = 64;
+  else
+    projected_n_tokens++;      /* add one for trailing NULL pointer */
+
   sz = projected_n_tokens;
-  tokens = xmalloc (sz * sizeof (char *));
-  lengths = xmalloc (sz * sizeof (long));
+  tokens = xnmalloc (sz, sizeof *tokens);
+  lengths = xnmalloc (sz, sizeof *lengths);
 
+  n_tokens = 0;
   init_tokenbuffer (token);
   for (;;)
     {
       char *tmp;
-      token_length = readtoken (stream, delim, n_delim, token);
+      size_t token_length = readtoken (stream, delim, n_delim, token);
       if (n_tokens >= sz)
        {
-         sz *= 2;
-         tokens = xrealloc (tokens, sz * sizeof (char *));
-         lengths = xrealloc (lengths, sz * sizeof (long));
+         tokens = x2nrealloc (tokens, &sz, sizeof *tokens);
+         lengths = xnrealloc (lengths, sz, sizeof *lengths);
        }
 
-      if (token_length < 0)
+      if (token_length == (size_t) -1)
        {
          /* don't increment n_tokens for NULL entry */
          tokens[n_tokens] = NULL;
-         lengths[n_tokens] = -1;
+         lengths[n_tokens] = 0;
          break;
        }
-      tmp = xmalloc ((token_length + 1) * sizeof (char));
+      tmp = xnmalloc (token_length + 1, sizeof *tmp);
       lengths[n_tokens] = token_length;
-      tokens[n_tokens] = strncpy (tmp, token->buffer,
-                                 (unsigned) (token_length + 1));
+      tokens[n_tokens] = memcpy (tmp, token->buffer, token_length + 1);
       n_tokens++;
     }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]