summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2009-08-19 17:55:03 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2009-08-19 17:55:03 +0200
commit131f5592347929c3d28a4a9406e242e2cfdd5db9 (patch)
treea7434fb93b1856665c34380a77f655a54bae0332
parent44f3e1486fb5fd45644683af83aaaf27047e4250 (diff)
Write data to an XML file.
File path for the XML file is read per channel from the 'xmlpath' option.
-rw-r--r--Makefile4
-rw-r--r--channel.c3
-rw-r--r--channel.h3
-rw-r--r--config.c10
-rw-r--r--export_xml.c68
-rw-r--r--export_xml.h9
-rw-r--r--main.c2
7 files changed, 94 insertions, 5 deletions
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 <libxml/tree.h>
+#include <libxml/xmlsave.h>
+
+#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();
}