bug-gnulib
[Top][All Lists]
Advanced

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

Re: [bug-gnulib] strfile: new module


From: Bruno Haible
Subject: Re: [bug-gnulib] strfile: new module
Date: Tue, 30 May 2006 21:59:52 +0200
User-agent: KMail/1.5

Simon Josefsson wrote:
> This is used in GnuTLS, and I need it in Shishi now, so I thought that
> it should be a module.  What do you think?

I agree it's common enough that we can use it in gnulib.

> Possibly, there should be a xstrfile too, that uses xrealloc...

Yes.

> Index: modules/strfile

I would call the module 'read-file' and the function 'read_file'. So that it's
possible to add a module 'write_file' if needed, and for consistency with the
'copy-file' module.

> +  do {

In GNU style the brace goes on the next line.

> +    tmp = realloc (out, pos + BUFSIZ);

Quadratic runtime behaviour: if you don't have particular luck with the 
realloc()
implementation, for large files, this loop will spend most of its time in
realloc(), copying memory around.

> +  if (!(feof (fh) && fclose (fh)))

Missing treatment of the ferror (fh) case.

As additional input, find attached some similar (unpolished) code I wrote long 
ago
in the past. The good point about a function that takes a FILE stream rather
than a filename as argument is that the caller has more liberty to decide
about O_TEXT / O_BINARY and about what to do when the file does not exist. The
downside is, of course, that it's not so immediate to use this function. But
maybe the module can provide both: fread_file that reads from a stream, and
read_file that takes a filename?

Bruno


=============================================================================
/* Read the contents of an input stream, and return it, terminated with a NUL
   byte. */
char* fread_file (FILE* stream)
{
#define BUFSIZE 4096
  char* buf = NULL;
  int alloc = 0;
  int size = 0;
  int count;

  while (!feof(stream))
    {
      if (size + BUFSIZE > alloc)
        {
          alloc = alloc + alloc/2;
          if (alloc < size + BUFSIZE)
            alloc = size + BUFSIZE;
          buf = realloc(buf,alloc);
          if (buf == NULL)
            {
              fprintf(stderr,"out of memory\n");
              exit(1);
            }
        }
      count = fread(buf+size,1,BUFSIZE,stream);
      if (count == 0)
        {
          if (ferror(stream))
            {
              perror("fread");
              exit(1);
            }
        }
      else
        {
          size += count;
        }
    }
  buf = realloc(buf,size+1);
  if (buf == NULL)
    {
      fprintf(stderr,"out of memory\n");
      exit(1);
    }
  buf[size] = '\0';
  return buf;
#undef BUFSIZE
}

/* Write a piece of memory to an output stream. */
void fwrite_file (FILE* stream, char* buf, int size)
{
  while (size > 0)
    {
      int count = fwrite(buf,1,size,stream);
      if (count == 0)
        {
          perror("fwrite");
          exit(1);
        }
      buf += count; size -= count;
    }
}





reply via email to

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