diff options
Diffstat (limited to 'src/client/text_writer.c')
-rw-r--r-- | src/client/text_writer.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/client/text_writer.c b/src/client/text_writer.c new file mode 100644 index 0000000..95990e7 --- /dev/null +++ b/src/client/text_writer.c @@ -0,0 +1,183 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2010 Andreas Hofmeister <andi@collax.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "writer.h" +#include "../log.h" + +static char sep[] = + "-------------------------------------------------------------------------------"; + +struct txt_writer_private { + FILE *fh; + int level; + int attrs; + int lastnl; +}; + +static void +txt_fprintf(struct txt_writer_private *p, const char *fmt, ...) +{ + va_list ap; + + // Don't add a newline if we already had one. + while (p->lastnl && fmt[0] == '\n') { + fmt += 1; + } + if (fmt[0] == '\0') return; + + va_start(ap, fmt); + vfprintf(p->fh, fmt, ap); + va_end(ap); + + p->lastnl = (strlen(fmt) > 0 && fmt[strlen(fmt) - 1] == '\n'); +} + +static void +txt_start(struct writer *w, const char *tag, const char *descr) +{ + struct txt_writer_private *p = w->priv; + int i = 0; + char buf[128]; + + if (p->level == 0) { + txt_fprintf(p, "%s\n", sep); + } else if (!p->lastnl) { + txt_fprintf(p, "\n"); + } + + for (i = 1; i < p->level; i++) { + txt_fprintf(p, " "); + } + + snprintf(buf, sizeof(buf), "%s:", descr); + txt_fprintf(p, "%-13s", buf); + + if (p->level == 0) txt_fprintf(p, "\n%s", sep); + + p->level++; + p->attrs = 0; +} + +static void +txt_attr(struct writer *w, const char *tag, const char *descr, const char *value) +{ + struct txt_writer_private *p = w->priv; + + if (descr == NULL || strlen(descr) == 0) { + txt_fprintf(p, "%s%s", (p->attrs > 0 ? ", " : " "), + value ? value : "(none)"); + } else { + txt_fprintf(p, "%s%s: %s", (p->attrs > 0 ? ", " : " "), descr, + value ? value : "(none)"); + } + + p->attrs++; +} + +static void +txt_data(struct writer *w, const char *data) +{ + struct txt_writer_private *p = w->priv; + char *nl, *begin; + char *v = begin = data ? strdup(data) : NULL; + + if (v == NULL) { + txt_fprintf(p, " %s", data ? data : "(none)"); + return; + } + + txt_fprintf(p, " "); + while ((nl = strchr(v, '\n')) != NULL) { + *nl = '\0'; + txt_fprintf(p, "%s\n", v); + v = nl + 1; + + /* Indent */ + int i; + for (i = 1; i < p->level - 1; i++) { + txt_fprintf(p, " "); + } + txt_fprintf(p, "%-14s", " "); + } + txt_fprintf(p, "%s", v); + free(begin); +} + +static void +txt_end(struct writer *w) +{ + struct txt_writer_private *p = w->priv; + p->level--; + + if (p->level == 1) { + txt_fprintf(p, "\n%s", sep); + fflush(p->fh); + } +} + +static void +txt_finish(struct writer *w) +{ + struct txt_writer_private *p = w->priv; + + txt_fprintf(p, "\n"); + + free(w->priv); + w->priv = NULL; + + free(w); +} + +struct writer * +txt_init(FILE *fh) +{ + + struct writer *result; + struct txt_writer_private *priv; + + priv = malloc(sizeof(*priv)); + if (!priv) { + fatalx("lldpctl", "out of memory"); + return NULL; + } + + priv->fh = fh; + priv->level = 0; + priv->attrs = 0; + priv->lastnl = 1; + + result = malloc(sizeof(struct writer)); + if (!result) { + fatalx("lldpctl", "out of memory"); + free(priv); + return NULL; + } + + result->priv = priv; + result->start = txt_start; + result->attr = txt_attr; + result->data = txt_data; + result->end = txt_end; + result->finish = txt_finish; + + return result; +} |