summaryrefslogtreecommitdiff
path: root/dynstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'dynstr.c')
-rw-r--r--dynstr.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/dynstr.c b/dynstr.c
index 99ef2ab..246c16f 100644
--- a/dynstr.c
+++ b/dynstr.c
@@ -9,6 +9,9 @@
#include "dynstr.h"
+#define DYNSTR_ERROR ((size_t) -1)
+
+
struct Dynstr {
const unsigned char *mem;
size_t size;
@@ -301,3 +304,68 @@ ssize_t dynstr_write(int fd, Dynstr *dynstr)
return write(fd, dynstr->mem, dynstr->size);
}
+
+static Dynstr *read_helper(size_t (*callback)(FILE *f, int fd, unsigned char *buf,
+ size_t size),
+ FILE *f, int fd, size_t size)
+{
+ unsigned char *buf;
+ unsigned char *p;
+ Dynstr *dynstr;
+ size_t n;
+
+ buf = alloc(size);
+ if (buf == NULL)
+ return NULL;
+
+ n = callback(f, fd, buf, size);
+ if (n == DYNSTR_ERROR) {
+ free(buf);
+ return NULL;
+ }
+
+ if (n < size) {
+ p = realloc(buf, n);
+ if (p != NULL)
+ buf = p;
+ }
+
+ dynstr = new(buf, n, false);
+ dynstr->dynamic = true;
+ return dynstr;
+}
+
+
+static size_t fread_callback(FILE *f, int fd, unsigned char *buf, size_t size)
+{
+ size_t n;
+
+ n = fread(buf, 1, size, f);
+ if (n == 0 && ferror(f))
+ return DYNSTR_ERROR;
+ return n;
+}
+
+
+static size_t read_callback(FILE *f, int fd, unsigned char *buf, size_t size)
+{
+ ssize_t n;
+
+ n = read(fd, buf, size);
+ if (n == -1)
+ return DYNSTR_ERROR;
+ return n;
+}
+
+
+Dynstr *dynstr_fread(FILE *file, size_t size)
+{
+ return read_helper(fread_callback, file, -1, size);
+}
+
+
+Dynstr *dynstr_read(int file, size_t size)
+{
+ return read_helper(read_callback, NULL, file, size);
+}
+