summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorP. J. McDermott <pjm@nac.net>2013-02-17 01:20:49 (EST)
committer P. J. McDermott <pjm@nac.net>2013-02-17 01:20:49 (EST)
commit1a8f91467aad191721d57a9ad772f6700c029e1d (patch)
tree4790ccd415cdd5e4fa22acaae7347520b5bcd296 /src
parent1e4407da677dd7a192c817de16583bb7199ceeb0 (diff)
downloadoverworld-rpg-1a8f91467aad191721d57a9ad772f6700c029e1d.zip
overworld-rpg-1a8f91467aad191721d57a9ad772f6700c029e1d.tar.gz
overworld-rpg-1a8f91467aad191721d57a9ad772f6700c029e1d.tar.bz2
TMX parser rewrite number two.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/main.c7
-rw-r--r--src/resources/map.c593
-rw-r--r--src/resources/map.h11
-rw-r--r--src/xml.c62
-rw-r--r--src/xml.h5
6 files changed, 364 insertions, 315 deletions
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 <expat.h>
#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("</%s> (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 <tileset> can contain:
- * * Zero or one <properties>,
- * * Zero or one <image>s, and
- * * Zero or more <tile>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("</%s> (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("</%s> (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("</%s> (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("</%s> (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("</%s> (type \"data\")", el);
+ XML_Parser p = (XML_Parser) pv;
+ struct tileset *ts;
- tmx = (struct tmx *) data;
+ debug("</%s> (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("</%s> (type \"object\")", el);
+ XML_Parser p = (XML_Parser) pv;
+ struct image *img;
+ struct tileset *ts;
- tmx = (struct tmx *) data;
+ debug("</%s> (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 <SDL_stdinc.h>
#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