From 131f5592347929c3d28a4a9406e242e2cfdd5db9 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Wed, 19 Aug 2009 17:55:03 +0200 Subject: Write data to an XML file. File path for the XML file is read per channel from the 'xmlpath' option. --- Makefile | 4 +++- channel.c | 3 ++- channel.h | 3 ++- config.c | 10 +++++++-- export_xml.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ export_xml.h | 9 ++++++++ main.c | 2 ++ 7 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 export_xml.c create mode 100644 export_xml.h diff --git a/Makefile b/Makefile index f3e182f..34f989a 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,11 @@ CFLAGS += -std=c99 -g CFLAGS += -D_GNU_SOURCE CFLAGS += $(shell pkg-config --cflags libconfig) CFLAGS += $(shell pcre-config --cflags) +CFLAGS += $(shell xml2-config --cflags) LDFLAGS += $(shell pkg-config --libs libconfig) LDFLAGS += $(shell pcre-config --libs) -OBJECTS = main.o config.o regexset.o channel.o user.o word.o sdbm.o +LDFLAGS += $(shell xml2-config --libs) +OBJECTS = main.o config.o regexset.o channel.o user.o word.o sdbm.o export_xml.o TARGET = ircstats all: $(TARGET) diff --git a/channel.c b/channel.c index c69cf2b..86e993d 100644 --- a/channel.c +++ b/channel.c @@ -13,7 +13,7 @@ void channel_init() { channel_count = 0; } -struct channel_t *channel_add(const char *name) { +struct channel_t *channel_add(const char *name, const char *xmlpath) { channels = realloc(channels, ++channel_count * sizeof(struct channel_t)); if(!channels) { char *error = strerror(errno); @@ -22,6 +22,7 @@ struct channel_t *channel_add(const char *name) { } struct channel_t *channel = &channels[channel_count-1]; channel->name = strdup(name); + channel->xmlpath = strdup(xmlpath); channel->files = NULL; memset(channel->hours, 0, 24*4 * sizeof(unsigned long)); return channel; diff --git a/channel.h b/channel.h index 0335782..3f4e4cd 100644 --- a/channel.h +++ b/channel.h @@ -11,13 +11,14 @@ struct channel_file_t { struct channel_t { char *name; + char *xmlpath; struct channel_file_t *files; unsigned long hours[24*4]; }; void channel_init(); -struct channel_t *channel_add(const char *name); +struct channel_t *channel_add(const char *name, const char *xmlpath); struct channel_file_t *channel_file_add(struct channel_t *channel, const char *path, int rs_index); int channel_get_count(); struct channel_t *channel_get(int index); diff --git a/config.c b/config.c index d50c90b..79eae42 100644 --- a/config.c +++ b/config.c @@ -52,15 +52,21 @@ int cfg_init() { int channel_count = config_setting_length(channels_setting); for(int i = 0; i < channel_count; i++) { config_setting_t *channel_setting = config_setting_get_elem(channels_setting, i); - const char *name; + const char *name, *xmlpath; if(!config_setting_lookup_string(channel_setting, "name", &name)) { char *sname; sname = malloc(sizeof(char) * 16); sprintf(sname, "channel #%d", i+1); name = sname; } + if(!config_setting_lookup_string(channel_setting, "xmlpath", &xmlpath)) { + /* Index-based filename if xmlpath isn't set. */ + char temp[0xf]; + sprintf(temp, "%d.xml", i); + xmlpath = strdup(temp); + } struct channel_t *channel; - if(!(channel = channel_add(name))) { + if(!(channel = channel_add(name, xmlpath))) { return 0; } config_setting_t *files = config_setting_get_member(channel_setting, "files"); diff --git a/export_xml.c b/export_xml.c new file mode 100644 index 0000000..f66381e --- /dev/null +++ b/export_xml.c @@ -0,0 +1,68 @@ +#include +#include + +#include "export_xml.h" + +#if !defined(LIBXML_TREE_ENABLED) +#error "libxml must be compiled with tree support" +#endif + + +int export_xml(struct channel_t *channel, struct user_t *users) { + /* Create document and set root node. */ + xmlDocPtr doc = xmlNewDoc("1.0"); + xmlNodePtr root_node = xmlNewNode(NULL, "channel"); + xmlDocSetRootElement(doc, root_node); + + /* Set the channel name. */ + xmlNewChild(root_node, NULL, "name", channel->name); + + /* Add lines. */ + xmlNodePtr lines_node = xmlNewChild(root_node, NULL, "lines", NULL); + for(int h = 0; h < 24; h++) { + xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, "hour", NULL); + for(int q = 0; q < 4; q++) { + char s[0xf]; + sprintf(s, "%d", channel->hours[h*4 + q]); + xmlNewChild(hour_node, NULL, "quarter", s); + } + } + + /* Add users. */ + xmlNodePtr users_node = xmlNewChild(root_node, NULL, "users", NULL); + for(int u = 0; u < USERS_MAX; u++) { + struct user_t *user = &users[u]; + /* Iterate while we have a user (nick is non-NULL). */ + while(user && user->nick) { + char s[0xf]; + xmlNodePtr user_node = xmlNewChild(users_node, NULL, "user", NULL); + + xmlNewChild(user_node, NULL, "nick", user->nick); + sprintf(s, "%d", user->words); + xmlNewChild(user_node, NULL, "words", s); + + /* Add lines for this user. */ + xmlNodePtr lines_node = xmlNewChild(users_node, NULL, "lines", NULL); + for(int h = 0; h < 24; h++) { + xmlNodePtr hour_node = xmlNewChild(lines_node, NULL, "hour", NULL); + for(int q = 0; q < 4; q++) { + sprintf(s, "%d", user->lines[h*4 + q]); + xmlNewChild(hour_node, NULL, "quarter", s); + } + } + user = user->next; + } + } + + xmlSaveCtxtPtr save_context = xmlSaveToFilename(channel->xmlpath, "UTF-8", 0); + if(!save_context) { + xmlErrorPtr error = xmlGetLastError(); + fprintf(stderr, "Failed to save XML data: %s\n", (error ? error->message : "unknown error")); + xmlFreeDoc(doc); + return 0; + } + xmlSaveDoc(save_context, doc); + xmlSaveClose(save_context); + xmlFreeDoc(doc); + return 1; +} diff --git a/export_xml.h b/export_xml.h new file mode 100644 index 0000000..f16379a --- /dev/null +++ b/export_xml.h @@ -0,0 +1,9 @@ +#ifndef _EXPORT_XML_H_ +#define _EXPORT_XML_H_ + +#include "channel.h" +#include "user.h" + +int export_xml(struct channel_t *channel, struct user_t *users); + +#endif diff --git a/main.c b/main.c index 8175dbe..1ccca8a 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "channel.h" #include "user.h" #include "word.h" +#include "export_xml.h" #define NICK_BUFFER_SIZE 0x100 #define TEXT_BUFFER_SIZE 0x400 @@ -109,6 +110,7 @@ int main(int argc, char **argv) { file = file->next; } + export_xml(channel, users); user_free(); word_free(); } -- cgit v1.2.3