diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2009-12-09 03:52:08 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2009-12-09 03:52:08 +0000 |
commit | 481a3f5110e03c2301e53837da2666114b5efa5c (patch) | |
tree | 77e1d1272c4252785583794324e5e7007da1d60e /lib/util/io.c | |
parent | ca1c1c7c4ca76728b3134cf685e8b8a6142e663b (diff) | |
download | netpbm-mirror-481a3f5110e03c2301e53837da2666114b5efa5c.tar.gz netpbm-mirror-481a3f5110e03c2301e53837da2666114b5efa5c.tar.xz netpbm-mirror-481a3f5110e03c2301e53837da2666114b5efa5c.zip |
new facilities needed by recently committed Pnmconvol updates: string list option type, token parsing, file line I/O
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1031 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/util/io.c')
-rw-r--r-- | lib/util/io.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/util/io.c b/lib/util/io.c new file mode 100644 index 00000000..edec4a7c --- /dev/null +++ b/lib/util/io.c @@ -0,0 +1,90 @@ +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#include "mallocvar.h" +#include "nstring.h" + +#include "io.h" + + +void +pm_freadline(FILE * const fileP, + const char ** const lineP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Read a line (assuming the file is text with lines delimited by newlines) + for file *fileP. Return that line in newly malloced storage as + *lineP. + + The newline delimiter is not part of the line. + + As a special case, if the file doesn't end in a newline, the characters + after the last newline are a line. + + If there are no more lines in the file, return *lineP == NULL. +-----------------------------------------------------------------------------*/ + char * buffer; + size_t bufferSize; + size_t cursor; + bool gotLine; + bool eof; + + bufferSize = 1024; /* initial value */ + *errorP = NULL; /* initial value */ + + MALLOCARRAY(buffer, bufferSize); + + for (cursor = 0, gotLine = false, eof = false; + !gotLine && !eof && !*errorP; ) { + if (cursor + 1 >= bufferSize) { + if (bufferSize > INT_MAX/2) { + free(buffer); + buffer = NULL; + } else { + bufferSize *= 2; + REALLOCARRAY(buffer, bufferSize); + } + } + + if (!buffer) + asprintfN(errorP, + "Couldn't get memory for a %u-byte file read buffer.", + (unsigned int)bufferSize); + else { + int const rc = getc(fileP); + + if (rc < 0) { + if (feof(fileP)) + eof = true; + else + asprintfN(errorP, "Failed to read a character from file. " + "Errno = %d (%s)", + errno, strerror(errno)); + } else { + char const c = (char)rc; + + if (c == '\n') + gotLine = true; + else { + buffer[cursor++] = c; + } + } + } + } + if (*errorP) { + if (buffer) + free(buffer); + } else { + if (eof && cursor == 0) { + *lineP = NULL; + free(buffer); + } else { + assert(cursor < bufferSize); + buffer[cursor++] = '\0'; + + *lineP = buffer; + } + } +} |