From 1a8f91467aad191721d57a9ad772f6700c029e1d Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sun, 17 Feb 2013 01:20:49 -0500 Subject: TMX parser rewrite number two. --- diff --git a/src/Makefile.am b/src/Makefile.am index 2ddbe94..a117d1e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,5 +7,4 @@ src_SOURCES = \ src/xml.c \ src/base64.c \ src/compression.c \ - src/tmx.c \ $(src_resources_SOURCES) diff --git a/src/main.c b/src/main.c index 24e9e1e..c867f65 100644 --- a/src/main.c +++ b/src/main.c @@ -2,20 +2,23 @@ #include "init.h" #include "logging.h" #include "resources/image.h" -#include "tmx.h" +#include "resources/map.h" int main(void) { + struct map *map; struct image *img; SDL_Rect imgrect, surfacerect; init(); - tmx_load("data/forest1.tmx"); + map = map_get("data/forest1.simple.tmx"); + printf("Map dimensions: %dx%d\n", map->width, map->height); img = img_png_get("../forest-6-layer-test_ground.png"); img_png_free(img); + return 0; img = img_png_get("../forest-6-layer-test_ground.png"); img = img_png_get("../forest-6-layer-test_ground.png"); img = img_png_get("../forest-6-layer-test_ground.png"); diff --git a/src/resources/map.c b/src/resources/map.c index b703629..6e5606b 100644 --- a/src/resources/map.c +++ b/src/resources/map.c @@ -4,420 +4,393 @@ #include #include "map.h" #include "resource.h" -#include "tileset.h" #include "../xml.h" #include "../logging.h" -struct tmx { - XML_Parser p; - struct map *map; - char *layer_data; -}; - +struct resource_table ts_res; struct resource_table map_res; -static void XMLCALL xml_map_start(void *data, const char *el, - const char **attr); -static void XMLCALL xml_map_end(void *data, const char *el); -static void XMLCALL xml_mapelem_start(void *data, const char *el, - const char **attr); -static void XMLCALL xml_mapelem_end(void *data, const char *el); -static void XMLCALL xml_image_start(void *data, const char *el, - const char **attr); -static void XMLCALL xml_image_end(void *data, const char *el); -static void XMLCALL xml_data_start(void *data, const char *el, - const char **attr); -static void XMLCALL xml_data_data(void *data, const char *s, int len); -static void XMLCALL xml_data_end(void *data, const char *el); -static void XMLCALL xml_object_start(void *data, const char *el, - const char **attr); -static void XMLCALL xml_object_end(void *data, const char *el); - -void map_add_layer(struct map *m, struct layer *l); -void map_add_tileset(struct map *m, struct tileset *t); +static struct tileset *tileset_get(const char *); +static void XMLCALL tmx_map_start(void *, const char *, const char **); +static void XMLCALL tmx_map_end(void *, const char *); +static void XMLCALL tmx_map_el_start(void *, const char *, const char **); +static void XMLCALL tmx_tileset_start(void *, const char *, const char **); +static void XMLCALL tmx_tileset_end(void *, const char *); +static void XMLCALL tmx_ext_ts_end(void *, const char *); +static void XMLCALL tmx_tileset_el_start(void *, const char *, const char **); +static void XMLCALL tmx_image_end(void *, const char *); +static void XMLCALL tmx_unused_start(void *, const char *, const char **); +static void XMLCALL tmx_unused_end(void *, const char *); +static void XMLCALL tmx_invalid_start(void *, const char *, const char **); +static void XMLCALL tmx_invalid_end(void *, const char *); -static void XMLCALL -xml_map_start(void *data, const char *el, const char **attr) +struct map * +map_get(const char *path) { - struct tmx *tmx; + struct map *map; + XML_Parser p; + FILE *tmx_fp; + void *tmx_buf; + size_t len; + enum XML_Status status; - debug("<%s> (type \"map\")", el); + map = (struct map *) resource_get(&map_res, path); + if (map != NULL) { + resource_use((struct resource *) map); + return map; + } + + p = XML_ParserCreate(NULL); + if (p == NULL) { + warn("Failed to create TMX parser"); + return NULL; + } - tmx = (struct tmx *) data; + XML_UseParserAsHandlerArg(p); + xml_node_push(p, map, tmx_map_start, tmx_invalid_end, NULL); - if (xml_check_tag(el, "map")) { - if (tmx->map != NULL) { - warn("Found multiple maps in TMX file"); - XML_StopParser(tmx->p, XML_FALSE); - } - tmx->map = malloc(sizeof(*tmx->map)); - if (tmx->map == NULL) { - warn("Failed to allocate map"); - XML_StopParser(tmx->p, XML_FALSE); + tmx_fp = fopen(path, "rb"); + if (tmx_fp == NULL) { + warn("Failed to open TMX file"); + xml_node_pop(p); + XML_ParserFree(p); + return NULL; + } + + tmx_buf = XML_GetBuffer(p, 8192); + if (tmx_buf == NULL) { + warn("Failed to create TMX parse buffer"); + xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); + return NULL; + } + + while (!feof(tmx_fp)) { + len = fread(tmx_buf, 1, 8192, tmx_fp); + status = XML_ParseBuffer(p, len, feof(tmx_fp)); + if (status == XML_STATUS_OK) { + continue; } - memset(tmx->map, 0, sizeof(*tmx->map)); - xml_get_int_attr(tmx->p, attr, "width", - &tmx->map->width, 1); - xml_get_int_attr(tmx->p, attr, "width", - &tmx->map->width, 1); - xml_get_int_attr(tmx->p, attr, "tilewidth", - &tmx->map->tilewidth, 1); - xml_get_int_attr(tmx->p, attr, "tileheight", - &tmx->map->tileheight, 1); - XML_SetStartElementHandler(tmx->p, xml_mapelem_start); - XML_SetEndElementHandler(tmx->p, xml_map_end); - } else { - xml_unexpected_start_tag(tmx->p, el, - "map"); + warn("Failed to parse TMX file (%s)", + XML_ErrorString(XML_GetErrorCode(p))); + xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); + return NULL; } -} -static void XMLCALL -xml_map_end(void *data, const char *el) -{ - struct tmx *tmx; + map = (struct map *) xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); - debug(" (type \"map\")", el); + resource_use((struct resource *) map); + resource_add(&map_res, path, (struct resource *) map); - tmx = (struct tmx *) data; + return map; +} - if (xml_check_tag(el, "map")) { - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, NULL); +void +map_add_layer(struct map *m, struct layer *l) +{ + if (m->layers_head == NULL) { + m->layers_head = l; } else { - xml_unexpected_end_tag(tmx->p, el, - "map"); + m->layers_tail->next = l; } + m->layers_tail = l; } -static void XMLCALL -xml_mapelem_start(void *data, const char *el, const char **attr) +void +map_add_tileset(struct map *m, struct tileset *t) +{ + if (m->tilesets_head == NULL) { + m->tilesets_head = t; + } else { + m->tilesets_tail->next = t; + } + m->tilesets_tail = t; +} + +static struct tileset * +tileset_get(const char *path) { - struct tmx *tmx; - char *source; struct tileset *ts; - struct layer *ly; + XML_Parser p; + FILE *tmx_fp; + void *tmx_buf; + size_t len; + enum XML_Status status; - debug("<%s> (type \"mapelem\")", el); + ts = (struct tileset *) resource_get(&ts_res, path); + if (ts != NULL) { + resource_use((struct resource *) ts); + return ts; + } - tmx = (struct tmx *) data; + p = XML_ParserCreate(NULL); + if (p == NULL) { + warn("Failed to create TSX parser"); + return NULL; + } - if (xml_check_tag(el, "tileset")) { - source = NULL; - xml_get_string_attr(tmx->p, attr, "source", - &source, 0); - if (source != NULL) { - ts = tileset_get(source); - free(source); - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_tileset_end); - } else { - ts = resource_alloc("", sizeof(*ts)); - xml_get_int_attr(tmx->p, attr, "tilewidth", - &ts->tilewidth, 1); - xml_get_int_attr(tmx->p, attr, "tileheight", - &ts->tileheight, 1); - /* TODO: Change xml_image_start to xml_tselem_start. - * A can contain: - * * Zero or one , - * * Zero or one s, and - * * Zero or more s. */ - XML_SetStartElementHandler(tmx->p, xml_image_start); - XML_SetEndElementHandler(tmx->p, xml_tileset_end); + XML_UseParserAsHandlerArg(p); + xml_node_push(p, ts, tmx_tileset_start, tmx_invalid_end, NULL); + + tmx_fp = fopen(path, "rb"); + if (tmx_fp == NULL) { + warn("Failed to open TSX file"); + xml_node_pop(p); + XML_ParserFree(p); + return NULL; + } + + tmx_buf = XML_GetBuffer(p, 8192); + if (tmx_buf == NULL) { + warn("Failed to create TSX parse buffer"); + xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); + return NULL; + } + + while (!feof(tmx_fp)) { + len = fread(tmx_buf, 1, 8192, tmx_fp); + status = XML_ParseBuffer(p, len, feof(tmx_fp)); + if (status == XML_STATUS_OK) { + continue; } - xml_get_int_attr(tmx->p, attr, "firstgid", - &ts->firstgid, 1); - xml_get_string_attr(tmx->p, attr, "name", - &ts->name, 1); - map_add_tileset(tmx->map, ts); - } else if (xml_check_tag(el, "layer")) { - ly = resource_alloc("", sizeof(*ly)); - xml_get_string_attr(tmx->p, attr, "name", - &ly->name, 1); - map_add_layer(tmx->map, ly); - XML_SetStartElementHandler(tmx->p, xml_data_start); - XML_SetEndElementHandler(tmx->p, xml_mapelem_end); - } else if (xml_check_tag(el, "objectgroup")) { - XML_SetStartElementHandler(tmx->p, xml_object_start); - XML_SetEndElementHandler(tmx->p, xml_mapelem_end); - } else { - xml_unexpected_start_tag(tmx->p, el, - "tileset, layer, or objectgroup"); + warn("Failed to parse TSX file (%s)", + XML_ErrorString(XML_GetErrorCode(p))); + xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); + return NULL; } + + ts = (struct tileset *) xml_node_pop(p); + XML_ParserFree(p); + fclose(tmx_fp); + + resource_use((struct resource *) ts); + resource_add(&ts_res, path, (struct resource *) ts); + + return ts; } static void XMLCALL -xml_mapelem_end(void *data, const char *el) +tmx_map_start(void *pv, const char *name, const char **attr) { - struct tmx *tmx; + XML_Parser p = (XML_Parser) pv; + struct map *m; - debug(" (type \"mapelem\")", el); + debug("<%s> (map)", name); - tmx = (struct tmx *) data; - - if (xml_check_tag(el, "tileset")) { - XML_SetStartElementHandler(tmx->p, xml_mapelem_start); - XML_SetEndElementHandler(tmx->p, xml_map_end); - } else if (xml_check_tag(el, "layer")) { - XML_SetStartElementHandler(tmx->p, xml_mapelem_start); - XML_SetEndElementHandler(tmx->p, xml_map_end); - } else if (xml_check_tag(el, "objectgroup")) { - XML_SetStartElementHandler(tmx->p, xml_mapelem_start); - XML_SetEndElementHandler(tmx->p, xml_map_end); + if (xml_check_tag(name, "map")) { + m = resource_alloc("", sizeof(*m)); + if (m == NULL) { + XML_StopParser(p, XML_FALSE); + return; + } + xml_get_int_attr(p, attr, "width", &m->width, 1); + xml_get_int_attr(p, attr, "height", &m->height, 1); + xml_get_int_attr(p, attr, "tilewidth", &m->tilewidth, 1); + xml_get_int_attr(p, attr, "tileheight", &m->tileheight, 1); + debug("pushing node"); + xml_node_push(p, m, tmx_map_el_start, tmx_map_end, NULL); } else { - xml_unexpected_end_tag(tmx->p, el, - "tileset, layer, or objectgroup"); + xml_unexpected_start_tag(p, name, "map"); } } static void XMLCALL -xml_image_start(void *data, const char *el, const char **attr) +tmx_map_end(void *pv, const char *name) { - struct tmx *tmx; - struct tileset *ts; - char *source; - - debug("<%s> (type \"image\")", el); + XML_Parser p = (XML_Parser) pv; + struct map *m; - tmx = (struct tmx *) data; + debug(" (map)", name); - if (xml_check_tag(el, "image")) { - ts = tmx->map->tilesets_tail; - xml_get_string_attr(tmx->p, attr, "source", - &source, 1); - ts->image = img_png_get(source); - free(source); - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_image_end); + if (xml_check_tag(name, "map")) { + /* A hack to expose the map back to map_get(). */ + m = xml_node_pop(p); + xml_node_push(p, m, tmx_invalid_start, tmx_invalid_end, NULL); } else { - xml_unexpected_end_tag(tmx->p, el, - "image"); + xml_unexpected_end_tag(p, name, "map"); } } static void XMLCALL -xml_image_end(void *data, const char *el) +tmx_map_el_start(void *pv, const char *name, const char **attr) { - struct tmx *tmx; - - tmx = (struct tmx *) data; + XML_Parser p = (XML_Parser) pv; + char *source; + struct tileset *ts; - debug(" (type \"image\")", el); + debug("<%s> (map child)", name); - if (xml_check_tag(el, "image")) { - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_mapelem_end); + if (xml_check_tag(name, "properties")) { + /* Not used by engine. */ + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); + } else if (xml_check_tag(name, "tileset")) { + source = NULL; + xml_get_string_attr(p, attr, "source", &source, 0); + if (source != NULL) { + /* External tilesheet. */ + ts = tileset_get(source); + free(source); + xml_node_push(p, ts, tmx_invalid_start, tmx_ext_ts_end, + NULL); + } else { + /* Pass through. */ + tmx_tileset_start(pv, name, attr); + ts = (struct tileset *) xml_node_peek(p); + } + xml_get_int_attr(p, attr, "firstgid", &ts->firstgid, 1); + xml_get_string_attr(p, attr, "name", &ts->name, 1); } else { - xml_unexpected_end_tag(tmx->p, el, - "image"); + xml_unexpected_start_tag(p, name, + "properties, tileset, layer, or objectgroup"); } } static void XMLCALL -xml_data_start(void *data, const char *el, const char **attr) +tmx_tileset_start(void *pv, const char *name, const char **attr) { - struct tmx *tmx; - struct layer *ly; - - debug("<%s> (type \"data\")", el); - - tmx = (struct tmx *) data; - - if (xml_check_tag(el, "data")) { - ly = tmx->map->layers_tail; - xml_get_string_attr(tmx->p, attr, "encoding", - &ly->encoding, 0); - xml_get_string_attr(tmx->p, attr, "compression", - &ly->compression, 0); - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_data_end); - XML_SetCharacterDataHandler(tmx->p, xml_data_data); + XML_Parser p = (XML_Parser) pv; + struct tileset *ts; + + debug("<%s> (tileset)", name); + + if (xml_check_tag(name, "tileset")) { + ts = resource_alloc("", sizeof(*ts)); + xml_get_string_attr(p, attr, "name", &ts->name, 1); + xml_get_int_attr(p, attr, "tilewidth", &ts->tilewidth, 1); + xml_get_int_attr(p, attr, "tileheight", &ts->tileheight, 1); + xml_node_push(p, ts, tmx_tileset_el_start, tmx_tileset_end, + NULL); } else { - xml_unexpected_start_tag(tmx->p, el, - "data"); + xml_unexpected_start_tag(p, name, "tileset"); } } static void XMLCALL -xml_data_data(void *data, const char *s, int len) +tmx_tileset_end(void *pv, const char *name) { - struct tmx *tmx; - char *s_z; - char *s_z_trimmed, *s_z_trimmed_end; - - debug("...LAYER DATA..."); - - tmx = (struct tmx *) data; + XML_Parser p = (XML_Parser) pv; + struct tileset *ts; - s_z = s_z_trimmed = strndup(s, len); + debug(" (tileset)", name); - while(isspace(*s_z_trimmed)) { - ++s_z_trimmed; - --len; - } - if (*s_z_trimmed == '\0') { - return; - } - s_z_trimmed_end = s_z_trimmed + len - 1; - while (s_z_trimmed_end > s_z_trimmed && isspace(*s_z_trimmed_end)) { - --s_z_trimmed_end; + if (xml_check_tag(name, "tileset")) { + ts = (struct tileset *) xml_node_pop(p); + /* XXX?? */ + resource_use((struct resource *) ts); + resource_add(&ts_res, "", (struct resource *) ts); + } else { + xml_unexpected_end_tag(p, name, "tileset"); } - *(s_z_trimmed_end + 1) = '\0'; - - tmx->layer_data = strdup(s_z_trimmed); - - free(s_z); } static void XMLCALL -xml_data_end(void *data, const char *el) +tmx_ext_ts_end(void *pv, const char *name) { - struct tmx *tmx; - - debug(" (type \"data\")", el); + XML_Parser p = (XML_Parser) pv; + struct tileset *ts; - tmx = (struct tmx *) data; + debug(" (tileset link)", name); - if (xml_check_tag(el, "data")) { - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_mapelem_end); - XML_SetCharacterDataHandler(tmx->p, NULL); + if (xml_check_tag(name, "tileset")) { + ts = (struct tileset *) xml_node_pop(p); + map_add_tileset((struct map *) xml_node_peek(p), ts); } else { - xml_unexpected_end_tag(tmx->p, el, - "data"); + xml_unexpected_end_tag(p, name, "tileset"); } } static void XMLCALL -xml_object_start(void *data, const char *el, - const char **attr) +tmx_tileset_el_start(void *pv, const char *name, const char **attr) { - struct tmx *tmx; - char *type; - - debug("<%s> (type \"object\")", el); + XML_Parser p = (XML_Parser) pv; + char *source; + struct image *img; - tmx = (struct tmx *) data; + debug("<%s> (tileset child)", name); - if (xml_check_tag(el, "object")) { - /* TODO: Handle objects. */ - xml_get_string_attr(tmx->p, attr, "type", - &type, 1); - if (strcmp(type, "exit") == 0) { - } else if (strcmp(type, "exit") == 0) { - } - XML_SetStartElementHandler(tmx->p, NULL); - XML_SetEndElementHandler(tmx->p, xml_object_end); + if (xml_check_tag(name, "image")) { + xml_get_string_attr(p, attr, "source", &source, 0); + img = NULL; /*img_png_get(source);*/ + free(source); + xml_node_push(p, img, tmx_invalid_start, tmx_image_end, NULL); } else { - xml_unexpected_start_tag(tmx->p, el, - "object"); + xml_unexpected_start_tag(p, name, "image"); } } static void XMLCALL -xml_object_end(void *data, const char *el) +tmx_image_end(void *pv, const char *name) { - struct tmx *tmx; - - debug(" (type \"object\")", el); + XML_Parser p = (XML_Parser) pv; + struct image *img; + struct tileset *ts; - tmx = (struct tmx *) data; + debug(" (image)", name); - if (xml_check_tag(el, "object")) { - XML_SetStartElementHandler(tmx->p, xml_object_start); - XML_SetEndElementHandler(tmx->p, xml_mapelem_end); + if (xml_check_tag(name, "image")) { + img = (struct image *) xml_node_pop(p); + ts = (struct tileset *) xml_node_peek(p); + ts->image = img; } else { - xml_unexpected_end_tag(tmx->p, el, - "object"); + xml_unexpected_end_tag(p, name, "image"); } } -struct map * -map_get(const char *path) +static void XMLCALL +tmx_unused_start(void *pv, const char *name, const char **attr) { - struct tmx tmx; - FILE *tmx_fp; - void *tmx_buf; - size_t len; - enum XML_Status status; - - memset(&tmx, 0, sizeof(tmx)); + XML_Parser p = (XML_Parser) pv; - tmx.map = (struct map *) resource_get(&map_res, path); - if (tmx.map != NULL) { - resource_use((struct resource *) tmx.map); - return tmx.map; - } + debug("<%s> (unused)", name); - tmx.map = resource_alloc(path, sizeof(*tmx.map)); + /* Shut up, GCC. */ + for (; *name != '\0'; ++name); + for (; *attr != NULL; ++attr); - tmx.p = XML_ParserCreate(NULL); - if (tmx.p == NULL) { - warn("Failed to create TMX parser"); - return NULL; - } + xml_node_push(p, NULL, tmx_unused_start, tmx_unused_end, NULL); +} - XML_SetStartElementHandler(tmx.p, xml_map_start); - XML_SetEndElementHandler(tmx.p, NULL); - XML_SetCharacterDataHandler(tmx.p, NULL); +static void XMLCALL +tmx_unused_end(void *pv, const char *name) +{ + XML_Parser p = (XML_Parser) pv; - XML_SetUserData(tmx.p, &tmx); + debug("<%s> (unused)", name); - tmx_fp = fopen(path, "rb"); - if (tmx_fp == NULL) { - warn("Failed to open TMX file"); - XML_ParserFree(tmx.p); - return NULL; - } + /* Shut up, GCC. */ + for (; *name != '\0'; ++name); - tmx_buf = XML_GetBuffer(tmx.p, 8192); - if (tmx_buf == NULL) { - warn("Failed to create TMX parse buffer"); - XML_ParserFree(tmx.p); - fclose(tmx_fp); - return NULL; - } + xml_node_pop(p); +} - while (!feof(tmx_fp)) { - len = fread(tmx_buf, 1, 8192, tmx_fp); - status = XML_ParseBuffer(tmx.p, len, feof(tmx_fp)); - if (status == XML_STATUS_OK) { - continue; - } - warn("Failed to parse TMX file (%s)", - XML_ErrorString(XML_GetErrorCode(tmx.p))); - XML_ParserFree(tmx.p); - fclose(tmx_fp); - return NULL; - } +static void XMLCALL +tmx_invalid_start(void *pv, const char *name, const char **attr) +{ + XML_Parser p = (XML_Parser) pv; - XML_ParserFree(tmx.p); - fclose(tmx_fp); + debug("<%s> (invalid)", name); - resource_use((struct resource *) tmx.map); - resource_add(&map_res, path, (struct resource *) tmx.map); + /* Shut up, GCC. */ + for (; *attr != NULL; ++attr); - return tmx.map; + xml_unexpected_start_tag(p, name, ""); } -void -map_add_layer(struct map *m, struct layer *l) +static void XMLCALL +tmx_invalid_end(void *pv, const char *name) { - if (m->layers_head == NULL) { - m->layers_head = l; - } else { - m->layers_tail->next = l; - } - m->layers_tail = l; -} + XML_Parser p = (XML_Parser) pv; -void -map_add_tileset(struct map *m, struct tileset *t) -{ - if (m->tilesets_head == NULL) { - m->tilesets_head = t; - } else { - m->tilesets_tail->next = t; - } - m->tilesets_tail = t; + debug("<%s> (invalid)", name); + + xml_unexpected_end_tag(p, name, ""); } diff --git a/src/resources/map.h b/src/resources/map.h index 04fcf27..81ee0ec 100644 --- a/src/resources/map.h +++ b/src/resources/map.h @@ -3,9 +3,18 @@ #include #include "resource.h" -#include "tileset.h" +#include "image.h" #include "layer.h" +struct tileset { + struct resource res; + int firstgid; + char *name; + int tilewidth; + int tileheight; + struct image *image; + struct tileset *next; +}; struct map { struct resource res; int width; diff --git a/src/xml.c b/src/xml.c index 68a72ed..267b25e 100644 --- a/src/xml.c +++ b/src/xml.c @@ -4,10 +4,18 @@ #include "xml.h" #include "logging.h" +struct xml_node { + void *data; + XML_StartElementHandler start; + XML_EndElementHandler end; + XML_CharacterDataHandler charhndl; + struct xml_node *parent; +}; + inline int xml_check_tag(const char *found, const char *expected) { - return strcmp(found, expected) != 0; + return strcmp(found, expected) == 0; } inline void @@ -53,6 +61,7 @@ xml_get_string_attr(XML_Parser p, const char **attr, const char *name, for (; attr[0] != NULL; attr += 2) { if (strcmp(attr[0], name) == 0) { *dest = strdup(attr[1]); + return; } } if (req) { @@ -60,3 +69,54 @@ xml_get_string_attr(XML_Parser p, const char **attr, const char *name, XML_StopParser(p, XML_FALSE); } } + +void +xml_node_push(XML_Parser p, void *data, + XML_StartElementHandler start, XML_EndElementHandler end, + XML_CharacterDataHandler charhndl) +{ + struct xml_node *n; + + n = malloc(sizeof(*n)); + if (n == NULL) { + return; + } + n->data = data; + n->start = start; + n->end = end; + n->charhndl = charhndl; + n->parent = (struct xml_node *) XML_GetUserData(p); + XML_SetUserData(p, n); + XML_SetStartElementHandler(p, n->start); + XML_SetEndElementHandler(p, n->end); + XML_SetCharacterDataHandler(p, n->charhndl); +} + +void * +xml_node_pop(XML_Parser p) +{ + struct xml_node *n; + void *data; + + n = (struct xml_node *) XML_GetUserData(p); + data = n->data; + XML_SetUserData(p, n->parent); + free(n); + + n = (struct xml_node *) XML_GetUserData(p); + XML_SetStartElementHandler(p, n->start); + XML_SetEndElementHandler(p, n->end); + XML_SetCharacterDataHandler(p, n->charhndl); + + return data; +} + +void * +xml_node_peek(XML_Parser p) +{ + struct xml_node *n; + + n = (struct xml_node *) XML_GetUserData(p); + + return n->data; +} diff --git a/src/xml.h b/src/xml.h index 07f9c80..a863c9b 100644 --- a/src/xml.h +++ b/src/xml.h @@ -12,5 +12,10 @@ void xml_get_int_attr(XML_Parser p, const char **attr, const char *name, int *dest, int req); void xml_get_string_attr(XML_Parser p, const char **attr, const char *name, char **dest, int req); +void xml_node_push(XML_Parser p, void *data, + XML_StartElementHandler start, XML_EndElementHandler end, + XML_CharacterDataHandler charhndl); +void *xml_node_pop(XML_Parser p); +void *xml_node_peek(XML_Parser p); #endif -- cgit v0.9.1