summaryrefslogtreecommitdiffstats
path: root/src/util/vstring_vstream.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/util/vstring_vstream.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/util/vstring_vstream.c b/src/util/vstring_vstream.c
new file mode 100644
index 0000000..451cc50
--- /dev/null
+++ b/src/util/vstring_vstream.c
@@ -0,0 +1,267 @@
+/*++
+/* NAME
+/* vstring_vstream 3
+/* SUMMARY
+/* auto-resizing string library, standard I/O interface
+/* SYNOPSIS
+/* #include <vstring_vstream.h>
+/*
+/* int vstring_get_flags(vp, fp, flags)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* int flags
+/*
+/* int vstring_get_flags_nonl(vp, fp, flags)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* int flags
+/*
+/* int vstring_get_flags_null(vp, fp, flags)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* int flags
+/*
+/* int vstring_get_flags_bound(vp, fp, flags, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/* int flags
+/*
+/* int vstring_get_flags_nonl_bound(vp, fp, flags, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/* int flags
+/*
+/* int vstring_get_flags_null_bound(vp, fp, flags, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/* int flags
+/* CONVENIENCE API
+/* int vstring_get(vp, fp)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/*
+/* int vstring_get_nonl(vp, fp)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/*
+/* int vstring_get_null(vp, fp)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/*
+/* int vstring_get_bound(vp, fp, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/*
+/* int vstring_get_nonl_bound(vp, fp, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/*
+/* int vstring_get_null_bound(vp, fp, bound)
+/* VSTRING *vp;
+/* VSTREAM *fp;
+/* ssize_t bound;
+/* DESCRIPTION
+/* The routines in this module each read one newline or null-terminated
+/* string from an input stream. In all cases the result is either the
+/* last character read, typically the record terminator, or VSTREAM_EOF.
+/* The flags argument is VSTRING_GET_FLAG_NONE (default) or
+/* VSTRING_GET_FLAG_APPEND (append instead of overwrite).
+/*
+/* vstring_get_flags() reads one line from the named stream, including the
+/* terminating newline character if present.
+/*
+/* vstring_get_flags_nonl() reads a line from the named stream and strips
+/* the trailing newline character.
+/*
+/* vstring_get_flags_null() reads a null-terminated string from the named
+/* stream.
+/*
+/* the vstring_get_flags<whatever>_bound() routines read no more
+/* than \fIbound\fR characters. Otherwise they behave like the
+/* unbounded versions documented above.
+/*
+/* The functions without _flags in their name accept the same
+/* arguments except flags. These functions use the default
+/* flags value.
+/* DIAGNOSTICS
+/* Fatal errors: memory allocation failure.
+/* Panic: improper string bound.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Application-specific. */
+
+#include "msg.h"
+#include "vstring.h"
+#include "vstream.h"
+#include "vstring_vstream.h"
+
+ /*
+ * Macro to return the last character added to a VSTRING, for consistency.
+ */
+#define VSTRING_GET_RESULT(vp, baselen) \
+ (VSTRING_LEN(vp) > (base_len) ? vstring_end(vp)[-1] : VSTREAM_EOF)
+
+/* vstring_get_flags - read line from file, keep newline */
+
+int vstring_get_flags(VSTRING *vp, VSTREAM *fp, int flags)
+{
+ int c;
+ ssize_t base_len;
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
+ VSTRING_ADDCH(vp, c);
+ if (c == '\n')
+ break;
+ }
+ VSTRING_TERMINATE(vp);
+ return (VSTRING_GET_RESULT(vp, baselen));
+}
+
+/* vstring_get_flags_nonl - read line from file, strip newline */
+
+int vstring_get_flags_nonl(VSTRING *vp, VSTREAM *fp, int flags)
+{
+ int c;
+ ssize_t base_len;
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
+ VSTRING_ADDCH(vp, c);
+ VSTRING_TERMINATE(vp);
+ return (c == '\n' ? c : VSTRING_GET_RESULT(vp, baselen));
+}
+
+/* vstring_get_flags_null - read null-terminated string from file */
+
+int vstring_get_flags_null(VSTRING *vp, VSTREAM *fp, int flags)
+{
+ int c;
+ ssize_t base_len;
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
+ VSTRING_ADDCH(vp, c);
+ VSTRING_TERMINATE(vp);
+ return (c == 0 ? c : VSTRING_GET_RESULT(vp, baselen));
+}
+
+/* vstring_get_flags_bound - read line from file, keep newline, up to bound */
+
+int vstring_get_flags_bound(VSTRING *vp, VSTREAM *fp, int flags,
+ ssize_t bound)
+{
+ int c;
+ ssize_t base_len;
+
+ if (bound <= 0)
+ msg_panic("vstring_get_bound: invalid bound %ld", (long) bound);
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
+ VSTRING_ADDCH(vp, c);
+ if (c == '\n')
+ break;
+ }
+ VSTRING_TERMINATE(vp);
+ return (VSTRING_GET_RESULT(vp, baselen));
+}
+
+/* vstring_get_flags_nonl_bound - read line from file, strip newline, up to bound */
+
+int vstring_get_flags_nonl_bound(VSTRING *vp, VSTREAM *fp, int flags,
+ ssize_t bound)
+{
+ int c;
+ ssize_t base_len;
+
+ if (bound <= 0)
+ msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound);
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
+ VSTRING_ADDCH(vp, c);
+ VSTRING_TERMINATE(vp);
+ return (c == '\n' ? c : VSTRING_GET_RESULT(vp, baselen));
+}
+
+/* vstring_get_flags_null_bound - read null-terminated string from file */
+
+int vstring_get_flags_null_bound(VSTRING *vp, VSTREAM *fp, int flags,
+ ssize_t bound)
+{
+ int c;
+ ssize_t base_len;
+
+ if (bound <= 0)
+ msg_panic("vstring_get_null_bound: invalid bound %ld", (long) bound);
+
+ if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
+ VSTRING_RESET(vp);
+ base_len = VSTRING_LEN(vp);
+ while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
+ VSTRING_ADDCH(vp, c);
+ VSTRING_TERMINATE(vp);
+ return (c == 0 ? c : VSTRING_GET_RESULT(vp, baselen));
+}
+
+#ifdef TEST
+
+ /*
+ * Proof-of-concept test program: copy the source to this module to stdout.
+ */
+#include <fcntl.h>
+
+#define TEXT_VSTREAM "vstring_vstream.c"
+
+int main(void)
+{
+ VSTRING *vp = vstring_alloc(1);
+ VSTREAM *fp;
+
+ if ((fp = vstream_fopen(TEXT_VSTREAM, O_RDONLY, 0)) == 0)
+ msg_fatal("open %s: %m", TEXT_VSTREAM);
+ while (vstring_fgets(vp, fp))
+ vstream_fprintf(VSTREAM_OUT, "%s", vstring_str(vp));
+ vstream_fclose(fp);
+ vstream_fflush(VSTREAM_OUT);
+ vstring_free(vp);
+ return (0);
+}
+
+#endif