From 6049fe0e789884ac0589190495d68e470c0fe19c Mon Sep 17 00:00:00 2001 Message-Id: <6049fe0e789884ac0589190495d68e470c0fe19c.1714173406.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sat, 1 Dec 2007 11:04:44 +0000 Subject: [PATCH] sink.c tests + docs Organization: Straylight/Edgeware From: Richard Kettlewell --- lib/sink.c | 35 +++++++++++++++++++++++++++++++++++ lib/sink.h | 34 +++++++++++++++++++++++++++++++--- lib/test.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/lib/sink.c b/lib/sink.c index e09f037..245ee26 100644 --- a/lib/sink.c +++ b/lib/sink.c @@ -17,6 +17,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ +/** @file lib/sink.c + * @brief Abstract output sink type + */ #include #include "types.h" @@ -32,10 +35,21 @@ #include "log.h" #include "printf.h" +/** @brief Formatted output to a sink + * @param s Sink to write to + * @param fmt Format string + * @param ap Argument list + * @return Number of bytes written on success, -1 on error + */ int sink_vprintf(struct sink *s, const char *fmt, va_list ap) { return byte_vsinkprintf(s, fmt, ap); } +/** @brief Formatted output to a sink + * @param s Sink to write to + * @param fmt Format string + * @return Number of bytes written on success, -1 on error + */ int sink_printf(struct sink *s, const char *fmt, ...) { va_list ap; int n; @@ -48,14 +62,22 @@ int sink_printf(struct sink *s, const char *fmt, ...) { /* stdio sink *****************************************************************/ +/** @brief Sink that writes to a stdio @c FILE */ struct stdio_sink { + /** @brief Base member */ struct sink s; + + /** @brief Filename */ const char *name; + + /** @brief Stream to write to */ FILE *fp; }; +/** @brief Reinterpret a @ref sink as a @ref stdio_sink */ #define S(s) ((struct stdio_sink *)s) +/** @brief Write callback for @ref stdio_sink */ static int sink_stdio_write(struct sink *s, const void *buffer, int nbytes) { int n = fwrite(buffer, 1, nbytes, S(s)->fp); if(n < nbytes) { @@ -67,6 +89,11 @@ static int sink_stdio_write(struct sink *s, const void *buffer, int nbytes) { return n; } +/** @brief Create a sink that writes to a stdio stream + * @param name Filename for use in error messages + * @param fp Stream to write to + * @return Pointer to new sink + */ struct sink *sink_stdio(const char *name, FILE *fp) { struct stdio_sink *s = xmalloc(sizeof *s); @@ -78,16 +105,24 @@ struct sink *sink_stdio(const char *name, FILE *fp) { /* dynstr sink ****************************************************************/ +/** @brief Sink that writes to a dynamic string */ struct dynstr_sink { + /** @brief Base member */ struct sink s; + /** @brief Pointer to dynamic string to append to */ struct dynstr *d; }; +/** @brief Write callback for @ref dynstr_sink */ static int sink_dynstr_write(struct sink *s, const void *buffer, int nbytes) { dynstr_append_bytes(((struct dynstr_sink *)s)->d, buffer, nbytes); return nbytes; } +/** @brief Create a sink that appends to a @ref dynstr + * @param output Dynamic string to append to + * @return Pointer to new sink + */ struct sink *sink_dynstr(struct dynstr *output) { struct dynstr_sink *s = xmalloc(sizeof *s); diff --git a/lib/sink.h b/lib/sink.h index 291476e..6134501 100644 --- a/lib/sink.h +++ b/lib/sink.h @@ -17,17 +17,29 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ +/** @file lib/sink.h + * @brief Abstract output sink type + */ #ifndef SINK_H #define SINK_H -/* a sink is something you write to (the opposite would be a source) */ - struct dynstr; +/** @brief Sink type + * + * A sink is something you write bytes to; the opposite would be a + * source. We provide sink_stdio() and sink_dynstr() to create sinks + * to write to stdio streams and dynamic strings. + */ struct sink { + /** @brief Write callback + * @param s Sink to write to + * @param buffer First byte to write + * @param nbytes Number of bytes to write + * @return non-negative on success, -1 on error + */ int (*write)(struct sink *s, const void *buffer, int nbytes); - /* return >= 0 on success, -1 on error */ }; struct sink *sink_stdio(const char *name, FILE *fp); @@ -43,14 +55,30 @@ int sink_printf(struct sink *s, const char *fmt, ...) attribute((format (printf, 2, 3))); /* equivalent of vfprintf/fprintf for sink @s@ */ +/** @brief Write bytes to a sink + * @param s Sink to write to + * @param buffer First byte to write + * @param nbytes Number of bytes to write + * @return non-negative on success, -1 on error + */ static inline int sink_write(struct sink *s, const void *buffer, int nbytes) { return s->write(s, buffer, nbytes); } +/** @brief Write string to a sink + * @param s Sink to write to + * @param str String to write + * @return non-negative on success, -1 on error + */ static inline int sink_writes(struct sink *s, const char *str) { return s->write(s, str, strlen(str)); } +/** @brief Write one byte to a sink + * @param s Sink to write to + * @param c Byte to write (as a @c char) + * @return non-negative on success, -1 on error + */ static inline int sink_writec(struct sink *s, char c) { return s->write(s, &c, 1); } diff --git a/lib/test.c b/lib/test.c index 635c245..02deb02 100644 --- a/lib/test.c +++ b/lib/test.c @@ -52,6 +52,7 @@ #include "selection.h" #include "syscalls.h" #include "kvp.h" +#include "sink.h" static int tests, errors; static int fail_first; @@ -855,6 +856,34 @@ static void test_kvp(void) { "abc%25%20%2b%0a"); } +static void test_sink(void) { + struct sink *s; + struct dynstr d[1]; + FILE *fp; + char *l; + + fprintf(stderr, "test_sink\n"); + + fp = tmpfile(); + assert(fp != 0); + s = sink_stdio("tmpfile", fp); + insist(sink_printf(s, "test: %d\n", 999) == 10); + insist(sink_printf(s, "wibble: %s\n", "foobar") == 15); + rewind(fp); + insist(inputline("tmpfile", fp, &l, '\n') == 0); + check_string(l, "test: 999"); + insist(inputline("tmpfile", fp, &l, '\n') == 0); + check_string(l, "wibble: foobar"); + insist(inputline("tmpfile", fp, &l, '\n') == -1); + + dynstr_init(d); + s = sink_dynstr(d); + insist(sink_printf(s, "test: %d\n", 999) == 10); + insist(sink_printf(s, "wibble: %s\n", "foobar") == 15); + dynstr_terminate(d); + check_string(d->vec, "test: 999\nwibble: foobar\n"); +} + int main(void) { fail_first = !!getenv("FAIL_FIRST"); insist('\n' == 0x0A); @@ -893,6 +922,7 @@ int main(void) { /* printf.c */ /* queue.c */ /* sink.c */ + test_sink(); /* snprintf.c */ /* split.c */ /* syscalls.c */ -- [mdw]