Blame src/client/xml_writer.c

Packit e9ba0d
/* -*- mode: c; c-file-style: "openbsd" -*- */
Packit e9ba0d
/*
Packit e9ba0d
 * Copyright (c) 2010 Andreas Hofmeister <andi@collax.com>
Packit e9ba0d
 *
Packit e9ba0d
 * Permission to use, copy, modify, and/or distribute this software for any
Packit e9ba0d
 * purpose with or without fee is hereby granted, provided that the above
Packit e9ba0d
 * copyright notice and this permission notice appear in all copies.
Packit e9ba0d
 *
Packit e9ba0d
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Packit e9ba0d
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Packit e9ba0d
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Packit e9ba0d
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit e9ba0d
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
Packit e9ba0d
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Packit e9ba0d
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit e9ba0d
 */
Packit e9ba0d
Packit e9ba0d
#include <stdio.h>
Packit e9ba0d
#include <stdlib.h>
Packit e9ba0d
#include <string.h>
Packit e9ba0d
Packit e9ba0d
#if defined(__clang__)
Packit e9ba0d
#pragma clang diagnostic push
Packit e9ba0d
#pragma clang diagnostic ignored "-Wdocumentation"
Packit e9ba0d
#endif
Packit e9ba0d
#include <libxml/encoding.h>
Packit e9ba0d
#include <libxml/xmlwriter.h>
Packit e9ba0d
#if defined(__clang__)
Packit e9ba0d
#pragma clang diagnostic pop
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
#include "writer.h"
Packit e9ba0d
#include "../log.h"
Packit e9ba0d
Packit e9ba0d
struct xml_writer_private {
Packit e9ba0d
	FILE *fh;
Packit e9ba0d
	ssize_t depth;
Packit e9ba0d
	xmlTextWriterPtr xw;
Packit e9ba0d
	xmlDocPtr doc;
Packit e9ba0d
};
Packit e9ba0d
Packit e9ba0d
void xml_new_writer(struct xml_writer_private *priv)
Packit e9ba0d
{
Packit e9ba0d
	priv->xw = xmlNewTextWriterDoc(&(priv->doc), 0);
Packit e9ba0d
	if (!priv->xw)
Packit e9ba0d
		fatalx("lldpctl", "cannot create xml writer");
Packit e9ba0d
Packit e9ba0d
	xmlTextWriterSetIndent(priv->xw, 4);
Packit e9ba0d
Packit e9ba0d
	if (xmlTextWriterStartDocument(priv->xw, NULL, "UTF-8", NULL) < 0 )
Packit e9ba0d
		fatalx("lldpctl", "cannot start xml document");
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void xml_start(struct writer *w , const char *tag, const char *descr ) {
Packit e9ba0d
	struct xml_writer_private *p = w->priv;
Packit e9ba0d
Packit e9ba0d
	if (p->depth == 0)
Packit e9ba0d
		xml_new_writer(p);
Packit e9ba0d
Packit e9ba0d
	if (xmlTextWriterStartElement(p->xw, BAD_CAST tag) < 0)
Packit e9ba0d
		log_warnx("lldpctl", "cannot start '%s' element", tag);
Packit e9ba0d
Packit e9ba0d
	if (descr && (strlen(descr) > 0)) {
Packit e9ba0d
		if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST "label", "%s", descr) < 0)
Packit e9ba0d
			log_warnx("lldpctl", "cannot add attribute 'label' to element %s", tag);
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	p->depth++;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void xml_attr(struct writer *w, const char *tag, const char *descr, const char *value ) {
Packit e9ba0d
	struct xml_writer_private *p = w->priv;
Packit e9ba0d
Packit e9ba0d
	if (xmlTextWriterWriteFormatAttribute(p->xw, BAD_CAST tag, "%s", value?value:"") < 0)
Packit e9ba0d
		log_warnx("lldpctl", "cannot add attribute %s with value %s", tag, value?value:"(none)");
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void xml_data(struct writer *w, const char *data) {
Packit e9ba0d
	struct xml_writer_private *p = w->priv;
Packit e9ba0d
	if (xmlTextWriterWriteString(p->xw, BAD_CAST (data?data:"")) < 0 )
Packit e9ba0d
		log_warnx("lldpctl", "cannot add '%s' as data to element", data?data:"(none)");
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void xml_end(struct writer *w) {
Packit e9ba0d
	struct xml_writer_private *p = w->priv;
Packit e9ba0d
Packit e9ba0d
	if (xmlTextWriterEndElement(p->xw) < 0 )
Packit e9ba0d
		log_warnx("lldpctl", "cannot end element");
Packit e9ba0d
Packit e9ba0d
	if (--p->depth == 0) {
Packit e9ba0d
		int failed = 0;
Packit e9ba0d
Packit e9ba0d
		if (xmlTextWriterEndDocument(p->xw) < 0 ) {
Packit e9ba0d
			log_warnx("lldpctl", "cannot finish document");
Packit e9ba0d
			failed = 1;
Packit e9ba0d
		}
Packit e9ba0d
Packit e9ba0d
		xmlFreeTextWriter(p->xw);
Packit e9ba0d
		if (!failed) {
Packit e9ba0d
			xmlDocDump(p->fh, p->doc);
Packit e9ba0d
			fflush(p->fh);
Packit e9ba0d
		}
Packit e9ba0d
		xmlFreeDoc(p->doc);
Packit e9ba0d
	}
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
void xml_finish(struct writer *w) {
Packit e9ba0d
	struct xml_writer_private *p = w->priv;
Packit e9ba0d
	if (p->depth != 0) {
Packit e9ba0d
		log_warnx("lldpctl", "unbalanced tags");
Packit e9ba0d
		/* memory leak... */
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
	free(p);
Packit e9ba0d
	free(w);
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
struct writer *xml_init(FILE *fh) {
Packit e9ba0d
Packit e9ba0d
	struct writer *result;
Packit e9ba0d
	struct xml_writer_private *priv;
Packit e9ba0d
Packit e9ba0d
	priv = malloc(sizeof(*priv));
Packit e9ba0d
	if (!priv) {
Packit e9ba0d
		fatalx("lldpctl", "out of memory");
Packit e9ba0d
		return NULL;
Packit e9ba0d
	}
Packit e9ba0d
	priv->fh = fh;
Packit e9ba0d
	priv->depth = 0;
Packit e9ba0d
Packit e9ba0d
	result = malloc(sizeof(struct writer));
Packit e9ba0d
	if (!result)
Packit e9ba0d
		fatalx("lldpctl", "out of memory");
Packit e9ba0d
Packit e9ba0d
	result->priv  = priv;
Packit e9ba0d
	result->start = xml_start;
Packit e9ba0d
	result->attr  = xml_attr;
Packit e9ba0d
	result->data  = xml_data;
Packit e9ba0d
	result->end   = xml_end;
Packit e9ba0d
	result->finish= xml_finish;
Packit e9ba0d
Packit e9ba0d
	return result;
Packit e9ba0d
}