diff options
author | unknown <unknown@unknown> | 2009-10-23 04:29:39 +0000 |
---|---|---|
committer | unknown <unknown@unknown> | 2009-10-23 04:29:39 +0000 |
commit | ddf5c42f67757000d6ec7686b92a667c2a252dca (patch) | |
tree | e070b352fab4b285b7a4ea547d0cbfff9b7fb4d1 /src/dom.c | |
download | iksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.tar.gz iksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.tar.xz iksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.zip |
Imported from iksemel-1.3.tar.gz.
Diffstat (limited to 'src/dom.c')
-rw-r--r-- | src/dom.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/dom.c b/src/dom.c new file mode 100644 index 0000000..849bf20 --- /dev/null +++ b/src/dom.c @@ -0,0 +1,181 @@ +/* iksemel (XML parser for Jabber) +** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net> +** This code is free software; you can redistribute it and/or +** modify it under the terms of GNU Lesser General Public License. +*/ + +#include "common.h" +#include "iksemel.h" + +struct dom_data { + iks **iksptr; + iks *current; + size_t chunk_size; +}; + +static int +tagHook (struct dom_data *data, char *name, char **atts, int type) +{ + iks *x; + + if (IKS_OPEN == type || IKS_SINGLE == type) { + if (data->current) { + x = iks_insert (data->current, name); + } else { + ikstack *s; + s = iks_stack_new (data->chunk_size, data->chunk_size); + x = iks_new_within (name, s); + } + if (atts) { + int i=0; + while (atts[i]) { + iks_insert_attrib (x, atts[i], atts[i+1]); + i += 2; + } + } + data->current = x; + } + if (IKS_CLOSE == type || IKS_SINGLE == type) { + x = iks_parent (data->current); + if (iks_strcmp(iks_name(data->current), name) != 0) + return IKS_BADXML; + if (x) + data->current = x; + else { + *(data->iksptr) = data->current; + data->current = NULL; + } + } + return IKS_OK; +} + +static int +cdataHook (struct dom_data *data, char *cdata, size_t len) +{ + if (data->current) iks_insert_cdata (data->current, cdata, len); + return IKS_OK; +} + +static void +deleteHook (struct dom_data *data) +{ + if (data->current) iks_delete (data->current); + data->current = NULL; +} + +iksparser * +iks_dom_new (iks **iksptr) +{ + ikstack *s; + struct dom_data *data; + + *iksptr = NULL; + s = iks_stack_new (DEFAULT_DOM_CHUNK_SIZE, 0); + if (!s) return NULL; + data = iks_stack_alloc (s, sizeof (struct dom_data)); + data->iksptr = iksptr; + data->current = NULL; + data->chunk_size = DEFAULT_DOM_IKS_CHUNK_SIZE; + return iks_sax_extend (s, data, (iksTagHook *) tagHook, (iksCDataHook *) cdataHook, (iksDeleteHook *) deleteHook); +} + +void +iks_set_size_hint (iksparser *prs, size_t approx_size) +{ + size_t cs; + struct dom_data *data = iks_user_data (prs); + + cs = approx_size / 10; + if (cs < DEFAULT_DOM_IKS_CHUNK_SIZE) cs = DEFAULT_DOM_IKS_CHUNK_SIZE; + data->chunk_size = cs; +} + +iks * +iks_tree (const char *xml_str, size_t len, int *err) +{ + iksparser *prs; + iks *x; + int e; + + if (0 == len) len = strlen (xml_str); + prs = iks_dom_new (&x); + if (!prs) { + if (err) *err = IKS_NOMEM; + return NULL; + } + e = iks_parse (prs, xml_str, len, 1); + if (err) *err = e; + iks_parser_delete (prs); + return x; +} + +int +iks_load (const char *fname, iks **xptr) +{ + iksparser *prs; + char *buf; + FILE *f; + int len, done = 0; + int ret; + + *xptr = NULL; + + buf = iks_malloc (FILE_IO_BUF_SIZE); + if (!buf) return IKS_NOMEM; + ret = IKS_NOMEM; + prs = iks_dom_new (xptr); + if (prs) { + f = fopen (fname, "r"); + if (f) { + while (0 == done) { + len = fread (buf, 1, FILE_IO_BUF_SIZE, f); + if (len < FILE_IO_BUF_SIZE) { + if (0 == feof (f)) { + ret = IKS_FILE_RWERR; + break; + } + if (0 == len) ret = IKS_OK; + done = 1; + } + if (len > 0) { + int e; + e = iks_parse (prs, buf, len, done); + if (IKS_OK != e) { + ret = e; + break; + } + if (done) ret = IKS_OK; + } + } + fclose (f); + } else { + if (ENOENT == errno) ret = IKS_FILE_NOFILE; + else ret = IKS_FILE_NOACCESS; + } + iks_parser_delete (prs); + } + iks_free (buf); + return ret; +} + +int +iks_save (const char *fname, iks *x) +{ + FILE *f; + char *data; + int ret; + + ret = IKS_NOMEM; + data = iks_string (NULL, x); + if (data) { + ret = IKS_FILE_NOACCESS; + f = fopen (fname, "w"); + if (f) { + ret = IKS_FILE_RWERR; + if (fputs (data, f) >= 0) ret = IKS_OK; + fclose (f); + } + iks_free (data); + } + return ret; +} |