about summary refs log tree commit diff
path: root/lib/util/io.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-12-09 03:52:08 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2009-12-09 03:52:08 +0000
commit481a3f5110e03c2301e53837da2666114b5efa5c (patch)
tree77e1d1272c4252785583794324e5e7007da1d60e /lib/util/io.c
parentca1c1c7c4ca76728b3134cf685e8b8a6142e663b (diff)
downloadnetpbm-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.c90
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;
+        }
+    }
+}