summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO7
-rw-r--r--apps/samxml.c16
-rw-r--r--include/samus/xml.h32
-rw-r--r--samus/sa_xml.c214
4 files changed, 165 insertions, 104 deletions
diff --git a/TODO b/TODO
index c8cd318a..a55abd11 100644
--- a/TODO
+++ b/TODO
@@ -25,6 +25,13 @@ fix the shading code:
reuse more code in the parsing
error cleanup
+think about rewriting file stream api (as the ultimate STDIO replacement):
+ use function pointers?
+ dont use pipeline filter?
+ memoryfile
+ diskfile
+ filterfile -> (filters data from another file)
+
---
immediate plan:
diff --git a/apps/samxml.c b/apps/samxml.c
index ab5a82e1..c42d8036 100644
--- a/apps/samxml.c
+++ b/apps/samxml.c
@@ -5,21 +5,23 @@ int main(int argc, char **argv)
{
fz_error *error;
fz_file *file;
- sa_xmlnode *xml;
+ sa_xmlparser *parser;
+ sa_xmlitem *item;
error = fz_openfile(&file, argv[1], FZ_READ);
if (error)
fz_abort(error);
- error = sa_parsexml(&xml, file, 0);
+ error = sa_openxml(&parser, file, 0);
if (error)
fz_abort(error);
-
- fz_closefile(file);
-
- sa_debugxml(xml, 0);
- sa_dropxml(xml);
+ item = sa_xmlnext(parser);
+ if (item)
+ sa_debugxml(item, 0);
+
+ sa_closexml(parser);
+ fz_closefile(file);
return 0;
}
diff --git a/include/samus/xml.h b/include/samus/xml.h
index 04308b66..fa798cd3 100644
--- a/include/samus/xml.h
+++ b/include/samus/xml.h
@@ -1,22 +1,26 @@
/*
- * XML mini-dom based on Inferno's XML parser API.
- * This one uses expat and in-memory objects though... :(
+ * A simple XML parsing API based on Inferno's.
+ * Under the surface this one uses expat and in-memory objects,
+ * but that should not be visible through the API.
*/
-typedef struct sa_xmlnode_s sa_xmlnode;
+typedef struct sa_xmlparser_s sa_xmlparser;
+typedef struct sa_xmlitem_s sa_xmlitem;
-fz_error *sa_parsexml(sa_xmlnode **nodep, fz_file *file, int ns);
-void sa_debugxml(sa_xmlnode *node, int level);
-void sa_dropxml(sa_xmlnode *node);
+fz_error *sa_openxml(sa_xmlparser **spp, fz_file *file, int ns);
+void sa_debugxml(sa_xmlitem *item, int level);
+void sa_closexml(sa_xmlparser *sp);
-sa_xmlnode *sa_xmlup(sa_xmlnode *node);
-sa_xmlnode *sa_xmlnext(sa_xmlnode *node);
-sa_xmlnode *sa_xmldown(sa_xmlnode *node);
+sa_xmlitem *sa_xmlnext(sa_xmlparser *sp);
+void sa_xmldown(sa_xmlparser *sp);
+void sa_xmlup(sa_xmlparser *sp);
-int sa_isxmltext(sa_xmlnode *node);
-int sa_isxmltag(sa_xmlnode *node);
+int sa_isxmlerror(sa_xmlitem *item);
+int sa_isxmltext(sa_xmlitem *item);
+int sa_isxmltag(sa_xmlitem *item);
-char *sa_getxmlname(sa_xmlnode *node);
-char *sa_getxmlatt(sa_xmlnode *node, char *att);
-char *sa_getxmltext(sa_xmlnode *node);
+char *sa_getxmlerror(sa_xmlitem *item);
+char *sa_getxmlname(sa_xmlitem *item);
+char *sa_getxmlatt(sa_xmlitem *item, char *att);
+char *sa_getxmltext(sa_xmlitem *item);
diff --git a/samus/sa_xml.c b/samus/sa_xml.c
index a9b88de0..3dd4f02e 100644
--- a/samus/sa_xml.c
+++ b/samus/sa_xml.c
@@ -5,27 +5,41 @@
#define XMLBUFLEN 4096
-struct sa_xmlnode_s
+struct sa_xmlitem_s
{
char *name;
char **atts;
- sa_xmlnode *up;
- sa_xmlnode *down;
- sa_xmlnode *next;
+ sa_xmlitem *up;
+ sa_xmlitem *down;
+ sa_xmlitem *next;
};
struct sa_xmlparser_s
{
fz_error *error;
- sa_xmlnode *root;
- sa_xmlnode *head;
+ sa_xmlitem *root;
+ sa_xmlitem *head;
+ int downed;
};
+static void dropitem(sa_xmlitem *item)
+{
+ sa_xmlitem *next;
+ while (item)
+ {
+ next = item->next;
+ if (item->down)
+ dropitem(item->down);
+ fz_free(item);
+ item = next;
+ }
+}
+
static void onopentag(void *zp, const char *name, const char **atts)
{
struct sa_xmlparser_s *sp = zp;
- sa_xmlnode *node;
- sa_xmlnode *tail;
+ sa_xmlitem *item;
+ sa_xmlitem *tail;
int namelen;
int attslen;
int textlen;
@@ -46,8 +60,8 @@ static void onopentag(void *zp, const char *name, const char **atts)
textlen += strlen(atts[i]) + 1;
}
- node = fz_malloc(sizeof(sa_xmlnode) + attslen + namelen + textlen);
- if (!node)
+ item = fz_malloc(sizeof(sa_xmlitem) + attslen + namelen + textlen);
+ if (!item)
{
sp->error = fz_outofmem;
return;
@@ -55,45 +69,45 @@ static void onopentag(void *zp, const char *name, const char **atts)
/* copy strings to new memory */
- node->atts = (char**) (((char*)node) + sizeof(sa_xmlnode));
- node->name = ((char*)node) + sizeof(sa_xmlnode) + attslen;
- p = ((char*)node) + sizeof(sa_xmlnode) + attslen + namelen;
+ item->atts = (char**) (((char*)item) + sizeof(sa_xmlitem));
+ item->name = ((char*)item) + sizeof(sa_xmlitem) + attslen;
+ p = ((char*)item) + sizeof(sa_xmlitem) + attslen + namelen;
- strcpy(node->name, name);
+ strcpy(item->name, name);
for (i = 0; atts[i]; i++)
{
- node->atts[i] = p;
- strcpy(node->atts[i], atts[i]);
+ item->atts[i] = p;
+ strcpy(item->atts[i], atts[i]);
p += strlen(p) + 1;
}
- node->atts[i] = 0;
+ item->atts[i] = 0;
- /* link node into tree */
+ /* link item into tree */
- node->up = sp->head;
- node->down = nil;
- node->next = nil;
+ item->up = sp->head;
+ item->down = nil;
+ item->next = nil;
if (!sp->head)
{
- sp->root = node;
- sp->head = node;
+ sp->root = item;
+ sp->head = item;
return;
}
if (!sp->head->down)
{
- sp->head->down = node;
- sp->head = node;
+ sp->head->down = item;
+ sp->head = item;
return;
}
tail = sp->head->down;
while (tail->next)
tail = tail->next;
- tail->next = node;
- sp->head = node;
+ tail->next = item;
+ sp->head = item;
}
static void onclosetag(void *zp, const char *name)
@@ -142,26 +156,34 @@ static void ontext(void *zp, const char *buf, int len)
}
fz_error *
-sa_parsexml(sa_xmlnode **nodep, fz_file *file, int ns)
+sa_openxml(sa_xmlparser **spp, fz_file *file, int ns)
{
fz_error *error = nil;
- struct sa_xmlparser_s sp;
+ sa_xmlparser *sp;
XML_Parser xp;
char *buf;
int len;
- sp.error = nil;
- sp.root = nil;
- sp.head = nil;
+ sp = fz_malloc(sizeof(sa_xmlparser));
+ if (!sp)
+ return fz_outofmem;
+
+ sp->error = nil;
+ sp->root = nil;
+ sp->head = nil;
+ sp->downed = 0;
if (ns)
xp = XML_ParserCreateNS(nil, ns);
else
xp = XML_ParserCreate(nil);
if (!xp)
+ {
+ fz_free(sp);
return fz_outofmem;
+ }
- XML_SetUserData(xp, &sp);
+ XML_SetUserData(xp, sp);
XML_SetParamEntityParsing(xp, XML_PARAM_ENTITY_PARSING_NEVER);
XML_SetStartElementHandler(xp, onopentag);
@@ -186,9 +208,10 @@ sa_parsexml(sa_xmlnode **nodep, fz_file *file, int ns)
goto cleanup;
}
- if (sp.error)
+ if (sp->error)
{
- error = sp.error;
+ error = sp->error;
+ sp->error = nil;
goto cleanup;
}
@@ -196,28 +219,24 @@ sa_parsexml(sa_xmlnode **nodep, fz_file *file, int ns)
break;
}
- *nodep = sp.root;
+ sp->head = nil;
+ *spp = sp;
return nil;
cleanup:
- if (sp.root)
- sa_dropxml(sp.root);
+ if (sp->root)
+ dropitem(sp->root);
+ fz_free(sp);
XML_ParserFree(xp);
return error;
}
void
-sa_dropxml(sa_xmlnode *node)
+sa_closexml(sa_xmlparser *sp)
{
- sa_xmlnode *next;
- while (node)
- {
- next = node->next;
- if (node->down)
- sa_dropxml(node->down);
- fz_free(node);
- node = next;
- }
+ if (sp->root)
+ dropitem(sp->root);
+ fz_free(sp);
}
static void indent(int n)
@@ -227,92 +246,121 @@ static void indent(int n)
}
void
-sa_debugxml(sa_xmlnode *node, int level)
+sa_debugxml(sa_xmlitem *item, int level)
{
int i;
- while (node)
+ while (item)
{
indent(level);
- if (sa_isxmltext(node))
- printf("%s\n", sa_getxmltext(node));
+ if (sa_isxmltext(item))
+ printf("%s\n", sa_getxmltext(item));
else
{
- printf("<%s", node->name);
+ printf("<%s", item->name);
- for (i = 0; node->atts[i]; i += 2)
- printf(" %s=\"%s\"", node->atts[i], node->atts[i+1]);
+ for (i = 0; item->atts[i]; i += 2)
+ printf(" %s=\"%s\"", item->atts[i], item->atts[i+1]);
- if (node->down)
+ if (item->down)
{
printf(">\n");
- sa_debugxml(node->down, level + 1);
+ sa_debugxml(item->down, level + 1);
indent(level);
- printf("</%s>\n", node->name);
+ printf("</%s>\n", item->name);
}
else
printf(" />\n");
}
- node = node->next;
+ item = item->next;
+ }
+}
+
+sa_xmlitem *
+sa_xmlnext(sa_xmlparser *sp)
+{
+ if (sp->downed)
+ return nil;
+
+ if (!sp->head)
+ {
+ sp->head = sp->root;
+ return sp->head;
+ }
+
+ if (sp->head->next)
+ {
+ sp->head = sp->head->next;
+ return sp->head;
}
+
+ return nil;
}
-sa_xmlnode *
-sa_xmlup(sa_xmlnode *node)
+void
+sa_xmldown(sa_xmlparser *sp)
{
- return node->up;
+ if (!sp->downed && sp->head && sp->head->down)
+ sp->head = sp->head->down;
+ else
+ sp->downed ++;
}
-sa_xmlnode *
-sa_xmlnext(sa_xmlnode *node)
+void
+sa_xmlup(sa_xmlparser *sp)
{
- return node->next;
+ if (!sp->downed && sp->head && sp->head->up)
+ sp->head = sp->head->up;
+ else
+ sp->downed --;
}
-sa_xmlnode *
-sa_xmldown(sa_xmlnode *node)
+int
+sa_isxmlerror(sa_xmlitem *item)
{
- return node->down;
+ return item->name[0] == '!';
}
int
-sa_isxmltext(sa_xmlnode *node)
+sa_isxmltext(sa_xmlitem *item)
{
- return node->name[0] == 0;
+ return item->name[0] == '\0';
}
int
-sa_isxmltag(sa_xmlnode *node)
+sa_isxmltag(sa_xmlitem *item)
{
- return node->name[0] != 0;
+ return item->name[0] != '\0' && item->name[0] != '!';
}
char *
-sa_getxmlname(sa_xmlnode *node)
+sa_getxmlname(sa_xmlitem *item)
{
- if (sa_isxmltag(node))
- return node->name;
+ if (sa_isxmltag(item))
+ return item->name;
return nil;
}
char *
-sa_getxmlatt(sa_xmlnode *node, char *att)
+sa_getxmlatt(sa_xmlitem *item, char *att)
{
int i;
- for (i = 0; node->atts[i]; i += 2)
- if (!strcmp(node->atts[i], att))
- return node->atts[i + 1];
+ if (sa_isxmltag(item))
+ {
+ for (i = 0; item->atts[i]; i += 2)
+ if (!strcmp(item->atts[i], att))
+ return item->atts[i + 1];
+ }
return nil;
}
char *
-sa_getxmltext(sa_xmlnode *node)
+sa_getxmltext(sa_xmlitem *item)
{
- if (sa_isxmltext(node))
- return node->atts[1];
+ if (sa_isxmltext(item))
+ return item->atts[1];
return nil;
}
-