summaryrefslogtreecommitdiffstats
path: root/src/client/xml_writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/xml_writer.c')
-rw-r--r--src/client/xml_writer.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/client/xml_writer.c b/src/client/xml_writer.c
new file mode 100644
index 0000000..0c5efb5
--- /dev/null
+++ b/src/client/xml_writer.c
@@ -0,0 +1,158 @@
+/* -*- 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 <string.h>
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+#include "writer.h"
+#include "../log.h"
+
+struct xml_writer_private {
+ FILE *fh;
+ ssize_t depth;
+ xmlTextWriterPtr xw;
+ xmlDocPtr doc;
+};
+
+static void
+xml_new_writer(struct xml_writer_private *priv)
+{
+ priv->xw = xmlNewTextWriterDoc(&(priv->doc), 0);
+ if (!priv->xw) fatalx("lldpctl", "cannot create xml writer");
+
+ xmlTextWriterSetIndent(priv->xw, 4);
+
+ if (xmlTextWriterStartDocument(priv->xw, NULL, "UTF-8", NULL) < 0)
+ fatalx("lldpctl", "cannot start xml document");
+}
+
+static void
+xml_start(struct writer *w, const char *tag, const char *descr)
+{
+ struct xml_writer_private *p = w->priv;
+
+ if (p->depth == 0) xml_new_writer(p);
+
+ if (xmlTextWriterStartElement(p->xw, BAD_CAST tag) < 0)
+ log_warnx("lldpctl", "cannot start '%s' element", tag);
+
+ if (descr && (strlen(descr) > 0)) {
+ if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST "label", "%s",
+ descr) < 0)
+ log_warnx("lldpctl",
+ "cannot add attribute 'label' to element %s", tag);
+ }
+
+ p->depth++;
+}
+
+static void
+xml_attr(struct writer *w, const char *tag, const char *descr, const char *value)
+{
+ struct xml_writer_private *p = w->priv;
+
+ if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST tag, "%s",
+ value ? value : "") < 0)
+ log_warnx("lldpctl", "cannot add attribute %s with value %s", tag,
+ value ? value : "(none)");
+}
+
+static void
+xml_data(struct writer *w, const char *data)
+{
+ struct xml_writer_private *p = w->priv;
+ if (xmlTextWriterWriteString(p->xw, BAD_CAST(data ? data : "")) < 0)
+ log_warnx("lldpctl", "cannot add '%s' as data to element",
+ data ? data : "(none)");
+}
+
+static void
+xml_end(struct writer *w)
+{
+ struct xml_writer_private *p = w->priv;
+
+ if (xmlTextWriterEndElement(p->xw) < 0)
+ log_warnx("lldpctl", "cannot end element");
+
+ if (--p->depth == 0) {
+ int failed = 0;
+
+ if (xmlTextWriterEndDocument(p->xw) < 0) {
+ log_warnx("lldpctl", "cannot finish document");
+ failed = 1;
+ }
+
+ xmlFreeTextWriter(p->xw);
+ if (!failed) {
+ xmlDocDump(p->fh, p->doc);
+ fflush(p->fh);
+ }
+ xmlFreeDoc(p->doc);
+ }
+}
+
+static void
+xml_finish(struct writer *w)
+{
+ struct xml_writer_private *p = w->priv;
+ if (p->depth != 0) {
+ log_warnx("lldpctl", "unbalanced tags");
+ /* memory leak... */
+ }
+
+ free(p);
+ free(w);
+}
+
+struct writer *
+xml_init(FILE *fh)
+{
+
+ struct writer *result;
+ struct xml_writer_private *priv;
+
+ priv = malloc(sizeof(*priv));
+ if (!priv) {
+ fatalx("lldpctl", "out of memory");
+ return NULL;
+ }
+ priv->fh = fh;
+ priv->depth = 0;
+
+ result = malloc(sizeof(struct writer));
+ if (!result) fatalx("lldpctl", "out of memory");
+
+ result->priv = priv;
+ result->start = xml_start;
+ result->attr = xml_attr;
+ result->data = xml_data;
+ result->end = xml_end;
+ result->finish = xml_finish;
+
+ return result;
+}