diff options
Diffstat (limited to 'xpdf/Zoox.cc')
-rw-r--r-- | xpdf/Zoox.cc | 1072 |
1 files changed, 1072 insertions, 0 deletions
diff --git a/xpdf/Zoox.cc b/xpdf/Zoox.cc new file mode 100644 index 0000000..9e4fb47 --- /dev/null +++ b/xpdf/Zoox.cc @@ -0,0 +1,1072 @@ +//======================================================================== +// +// Zoox.cc +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "gmem.h" +#include "gmempp.h" +#include "GString.h" +#include "GList.h" +#include "GHash.h" +#include "Zoox.h" + +//~ all of this code assumes the encoding is UTF-8 or ASCII or something +//~ similar (ISO-8859-*) + +//------------------------------------------------------------------------ + +static char nameStartChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +static char nameChar[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, // 20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 30 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 70 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // a0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // b0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // c0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // d0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // e0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // f0 +}; + +//------------------------------------------------------------------------ + +ZxNode::ZxNode() { + next = NULL; + parent = NULL; + firstChild = lastChild = NULL; +} + +ZxNode::~ZxNode() { + ZxNode *child; + + while (firstChild) { + child = firstChild; + firstChild = firstChild->next; + delete child; + } +} + +ZxNode *ZxNode::deleteChild(ZxNode *child) { + ZxNode *p1, *p2; + + for (p1 = NULL, p2 = firstChild; + p2 && p2 != child; + p1 = p2, p2 = p2->next) ; + if (!p2) { + return NULL; + } + if (p1) { + p1->next = child->next; + } else { + firstChild = child->next; + } + child->parent = NULL; + child->next = NULL; + return child; +} + +void ZxNode::appendChild(ZxNode *child) { + ZxNode *p1; + + if (child->parent || child->next) { + return; + } + if (firstChild) { + for (p1 = firstChild; p1->next; p1 = p1->next) ; + p1->next = child; + } else { + firstChild = child; + } + child->parent = this; +} + +void ZxNode::insertChildAfter(ZxNode *child, ZxNode *prev) { + if (child->parent || child->next || (prev && prev->parent != this)) { + return; + } + if (prev) { + child->next = prev->next; + prev->next = child; + } else { + child->next = firstChild; + firstChild = child; + } + child->parent = this; +} + +ZxElement *ZxNode::findFirstElement(const char *type) { + ZxNode *child; + ZxElement *result; + + if (isElement(type)) { + return (ZxElement *)this; + } + for (child = firstChild; child; child = child->next) { + if ((result = child->findFirstElement(type))) { + return result; + } + } + return NULL; +} + +ZxElement *ZxNode::findFirstChildElement(const char *type) { + ZxNode *child; + + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + return (ZxElement *)child; + } + } + return NULL; +} + +GList *ZxNode::findAllElements(const char *type) { + GList *results; + + results = new GList(); + findAllElements(type, results); + return results; +} + +void ZxNode::findAllElements(const char *type, GList *results) { + ZxNode *child; + + if (isElement(type)) { + results->append(this); + } + for (child = firstChild; child; child = child->next) { + child->findAllElements(type, results); + } +} + +GList *ZxNode::findAllChildElements(const char *type) { + GList *results; + ZxNode *child; + + results = new GList(); + for (child = firstChild; child; child = child->next) { + if (child->isElement(type)) { + results->append(child); + } + } + return results; +} + +void ZxNode::addChild(ZxNode *child) { + if (lastChild) { + lastChild->next = child; + lastChild = child; + } else { + firstChild = lastChild = child; + } + child->parent = this; + child->next = NULL; +} + +//------------------------------------------------------------------------ + +ZxDoc::ZxDoc() { + xmlDecl = NULL; + docTypeDecl = NULL; + root = NULL; +} + +ZxDoc *ZxDoc::loadMem(const char *data, Guint dataLen) { + ZxDoc *doc; + + doc = new ZxDoc(); + if (!doc->parse(data, dataLen)) { + delete doc; + return NULL; + } + return doc; +} + +ZxDoc *ZxDoc::loadFile(const char *fileName) { + ZxDoc *doc; + FILE *f; + char *data; + Guint dataLen; + + if (!(f = fopen(fileName, "rb"))) { + return NULL; + } + fseek(f, 0, SEEK_END); + dataLen = (Guint)ftell(f); + if (!dataLen) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_SET); + data = (char *)gmalloc(dataLen); + if (fread(data, 1, dataLen, f) != dataLen) { + fclose(f); + gfree(data); + return NULL; + } + fclose(f); + doc = loadMem(data, dataLen); + gfree(data); + return doc; +} + +ZxDoc::~ZxDoc() { +} + +static bool writeToFileFunc(void *stream, const char *data, int length) { + return (int)fwrite(data, 1, length, (FILE *)stream) == length; +} + +bool ZxDoc::writeFile(const char *fileName) { + FILE *f; + + if (!(f = fopen(fileName, "wb"))) { + return false; + } + write(&writeToFileFunc, f); + fclose(f); + return true; +} + +void ZxDoc::addChild(ZxNode *node) { + if (node->isXMLDecl() && !xmlDecl) { + xmlDecl = (ZxXMLDecl *)node; + } else if (node->isDocTypeDecl() && !docTypeDecl) { + docTypeDecl = (ZxDocTypeDecl *)node; + } else if (node->isElement() && !root) { + root = (ZxElement *)node; + } + ZxNode::addChild(node); +} + +bool ZxDoc::parse(const char *data, Guint dataLen) { + parsePtr = data; + parseEnd = data + dataLen; + + parseSpace(); + parseXMLDecl(this); + parseMisc(this); + parseDocTypeDecl(this); + parseMisc(this); + if (match("<")) { + parseElement(this); + } + parseMisc(this); + return root != NULL; +} + +void ZxDoc::parseXMLDecl(ZxNode *par) { + GString *version, *encoding, *s; + bool standalone; + + if (!match("<?xml")) { + return; + } + parsePtr += 5; + parseSpace(); + + // version + version = NULL; + if (match("version")) { + parsePtr += 7; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + version = parseQuotedString(); + } + } + if (!version) { + version = new GString("1.0"); + } + parseSpace(); + + // encoding + encoding = NULL; + if (match("encoding")) { + parsePtr += 8; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + encoding = parseQuotedString(); + } + } + parseSpace(); + + // standalone + standalone = false; + if (match("standalone")) { + parsePtr += 10; + parseSpace(); + if (match("=")) { + ++parsePtr; + parseSpace(); + s = parseQuotedString(); + standalone = !s->cmp("yes"); + delete s; + } + } + parseSpace(); + + if (match("?>")) { + parsePtr += 2; + } + + par->addChild(new ZxXMLDecl(version, encoding, standalone)); +} + +//~ this just skips everything after the name +void ZxDoc::parseDocTypeDecl(ZxNode *par) { + GString *name; + int state; + char c, quote; + + if (!match("<!DOCTYPE")) { + return; + } + parsePtr += 9; + parseSpace(); + + name = parseName(); + parseSpace(); + + state = 0; + quote = '\0'; + while (parsePtr < parseEnd && state < 4) { + c = *parsePtr++; + switch (state) { + case 0: // not in square brackets; not in quotes + if (c == '>') { + state = 4; + } else if (c == '"' || c == '\'') { + state = 1; + } else if (c == '[') { + state = 2; + } + break; + case 1: // not in square brackets; in quotes + if (c == quote) { + state = 0; + } + break; + case 2: // in square brackets; not in quotes + if (c == ']') { + state = 0; + } else if (c == '"' || c == '\'') { + state = 3; + } + break; + case 3: // in square brackets; in quotes + if (c == quote) { + state = 2; + } + break; + } + } + + par->addChild(new ZxDocTypeDecl(name)); +} + +// assumes match("<") +void ZxDoc::parseElement(ZxNode *par) { + GString *type; + ZxElement *elem; + ZxAttr *attr; + + ++parsePtr; + type = parseName(); + elem = new ZxElement(type); + parseSpace(); + while ((attr = parseAttr())) { + elem->addAttr(attr); + parseSpace(); + } + if (match("/>")) { + parsePtr += 2; + } else if (match(">")) { + ++parsePtr; + parseContent(elem); + } + par->addChild(elem); +} + +ZxAttr *ZxDoc::parseAttr() { + GString *name, *value; + const char *start; + char quote, c; + unsigned int x; + int n; + + name = parseName(); + parseSpace(); + if (!match("=")) { + delete name; + return NULL; + } + ++parsePtr; + parseSpace(); + if (!(parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\''))) { + delete name; + return NULL; + } + quote = *parsePtr++; + value = new GString(); + while (parsePtr < parseEnd && *parsePtr != quote) { + if (*parsePtr == '&') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == '#') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == 'x') { + ++parsePtr; + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(value, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + value->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + value->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + value->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + value->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + value->append('"'); + } else { + value->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != quote && *parsePtr != '&'; + ++parsePtr) ; + value->append(start, (int)(parsePtr - start)); + } + } + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + return new ZxAttr(name, value); +} + +// this consumes the end tag +void ZxDoc::parseContent(ZxElement *par) { + GString *endType; + + endType = (new GString("</"))->append(par->getType()); + + while (parsePtr < parseEnd) { + if (match(endType->getCString())) { + parsePtr += endType->getLength(); + parseSpace(); + if (match(">")) { + ++parsePtr; + } + break; + } else if (match("<?")) { + parsePI(par); + } else if (match("<![CDATA[")) { + parseCDSect(par); + } else if (match("<!--")) { + parseComment(par); + } else if (match("<")) { + parseElement(par); + } else { + parseCharData(par); + } + } + + delete endType; +} + +void ZxDoc::parseCharData(ZxElement *par) { + GString *data; + const char *start; + char c; + unsigned int x; + int n; + + data = new GString(); + while (parsePtr < parseEnd && *parsePtr != '<') { + if (*parsePtr == '&') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == '#') { + ++parsePtr; + if (parsePtr < parseEnd && *parsePtr == 'x') { + ++parsePtr; + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = (x << 4) + (c - '0'); + } else if (c >= 'a' && c <= 'f') { + x = (x << 4) + (10 + c - 'a'); + } else if (c >= 'A' && c <= 'F') { + x = (x << 4) + (10 + c - 'A'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } else { + x = 0; + while (parsePtr < parseEnd) { + c = *parsePtr; + if (c >= '0' && c <= '9') { + x = x * 10 + (c - '0'); + } else { + break; + } + ++parsePtr; + } + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + appendUTF8(data, x); + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != ';' && + *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + n = (int)(parsePtr - start); + if (parsePtr < parseEnd && *parsePtr == ';') { + ++parsePtr; + } + if (n == 2 && !strncmp(start, "lt", 2)) { + data->append('<'); + } else if (n == 2 && !strncmp(start, "gt", 2)) { + data->append('>'); + } else if (n == 3 && !strncmp(start, "amp", 3)) { + data->append('&'); + } else if (n == 4 && !strncmp(start, "apos", 4)) { + data->append('\''); + } else if (n == 4 && !strncmp(start, "quot", 4)) { + data->append('"'); + } else { + data->append(start - 1, (int)(parsePtr - start) + 1); + } + } + } else { + start = parsePtr; + for (++parsePtr; + parsePtr < parseEnd && *parsePtr != '<' && *parsePtr != '&'; + ++parsePtr) ; + data->append(start, (int)(parsePtr - start)); + } + } + par->addChild(new ZxCharData(data, true)); +} + +void ZxDoc::appendUTF8(GString *s, unsigned int c) { + if (c <= 0x7f) { + s->append((char)c); + } else if (c <= 0x7ff) { + s->append((char)(0xc0 + (c >> 6))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0xffff) { + s->append((char)(0xe0 + (c >> 12))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x1fffff) { + s->append((char)(0xf0 + (c >> 18))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x3ffffff) { + s->append((char)(0xf8 + (c >> 24))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } else if (c <= 0x7fffffff) { + s->append((char)(0xfc + (c >> 30))); + s->append((char)(0x80 + ((c >> 24) & 0x3f))); + s->append((char)(0x80 + ((c >> 18) & 0x3f))); + s->append((char)(0x80 + ((c >> 12) & 0x3f))); + s->append((char)(0x80 + ((c >> 6) & 0x3f))); + s->append((char)(0x80 + (c & 0x3f))); + } +} + +// assumes match("<![CDATA[") +void ZxDoc::parseCDSect(ZxNode *par) { + const char *start; + + parsePtr += 9; + start = parsePtr; + while (parsePtr < parseEnd - 3) { + if (!strncmp(parsePtr, "]]>", 3)) { + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxCharData(new GString(start, (int)(parsePtr - start)), + false)); +} + +void ZxDoc::parseMisc(ZxNode *par) { + while (1) { + if (match("<!--")) { + parseComment(par); + } else if (match("<?")) { + parsePI(par); + } else if (parsePtr < parseEnd && (*parsePtr == '\x20' || + *parsePtr == '\x09' || + *parsePtr == '\x0d' || + *parsePtr == '\x0a')) { + ++parsePtr; + } else { + break; + } + } +} + +// assumes match("<!--") +void ZxDoc::parseComment(ZxNode *par) { + const char *start; + + parsePtr += 4; + start = parsePtr; + while (parsePtr <= parseEnd - 3) { + if (!strncmp(parsePtr, "-->", 3)) { + par->addChild(new ZxComment(new GString(start, (int)(parsePtr - start)))); + parsePtr += 3; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; +} + +// assumes match("<?") +void ZxDoc::parsePI(ZxNode *par) { + GString *target; + const char *start; + + parsePtr += 2; + target = parseName(); + parseSpace(); + start = parsePtr; + while (parsePtr <= parseEnd - 2) { + if (!strncmp(parsePtr, "?>", 2)) { + par->addChild(new ZxPI(target, new GString(start, + (int)(parsePtr - start)))); + parsePtr += 2; + return; + } + ++parsePtr; + } + parsePtr = parseEnd; + par->addChild(new ZxPI(target, new GString(start, (int)(parsePtr - start)))); +} + +//~ this accepts all chars >= 0x80 +//~ this doesn't check for properly-formed UTF-8 +GString *ZxDoc::parseName() { + GString *name; + + name = new GString(); + if (parsePtr < parseEnd && nameStartChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + while (parsePtr < parseEnd && nameChar[*parsePtr & 0xff]) { + name->append(*parsePtr++); + } + } + return name; +} + +GString *ZxDoc::parseQuotedString() { + GString *s; + const char *start; + char quote; + + if (parsePtr < parseEnd && (*parsePtr == '"' || *parsePtr == '\'')) { + quote = *parsePtr++; + start = parsePtr; + while (parsePtr < parseEnd && *parsePtr != quote) { + ++parsePtr; + } + s = new GString(start, (int)(parsePtr - start)); + if (parsePtr < parseEnd && *parsePtr == quote) { + ++parsePtr; + } + } else { + s = new GString(); + } + return s; +} + +void ZxDoc::parseSpace() { + while (parsePtr < parseEnd && (*parsePtr == '\x20' || + *parsePtr == '\x09' || + *parsePtr == '\x0d' || + *parsePtr == '\x0a')) { + ++parsePtr; + } +} + +bool ZxDoc::match(const char *s) { + int n; + + n = (int)strlen(s); + return parseEnd - parsePtr >= n && !strncmp(parsePtr, s, n); +} + +bool ZxDoc::write(ZxWriteFunc writeFunc, void *stream) { + ZxNode *child; + + for (child = getFirstChild(); child; child = child->getNextChild()) { + if (!child->write(writeFunc, stream)) { + return false; + } + if (!(*writeFunc)(stream, "\n", 1)) { + return false; + } + } + return true; +} + +//------------------------------------------------------------------------ + +ZxXMLDecl::ZxXMLDecl(GString *versionA, GString *encodingA, bool standaloneA) { + version = versionA; + encoding = encodingA; + standalone = standaloneA; +} + +ZxXMLDecl::~ZxXMLDecl() { + delete version; + if (encoding) { + delete encoding; + } +} + +bool ZxXMLDecl::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("<?xml version=\""); + s->append(version); + s->append("\""); + if (encoding) { + s->append(" encoding=\""); + s->append(encoding); + s->append("\""); + } + if (standalone) { + s->append(" standlone=\"yes\""); + } + s->append("?>"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxDocTypeDecl::ZxDocTypeDecl(GString *nameA) { + name = nameA; +} + +ZxDocTypeDecl::~ZxDocTypeDecl() { + delete name; +} + +bool ZxDocTypeDecl::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("<!DOCTYPE "); + s->append(name); + s->append(">"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxComment::ZxComment(GString *textA) { + text = textA; +} + +ZxComment::~ZxComment() { + delete text; +} + +bool ZxComment::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("<!--"); + s->append(text); + s->append("-->"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxPI::ZxPI(GString *targetA, GString *textA) { + target = targetA; + text = textA; +} + +ZxPI::~ZxPI() { + delete target; + delete text; +} + +bool ZxPI::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + bool ok; + + s = new GString("<?"); + s->append(target); + s->append(" "); + s->append(text); + s->append("?>"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} + +//------------------------------------------------------------------------ + +ZxElement::ZxElement(GString *typeA) { + type = typeA; + attrs = new GHash(); + firstAttr = lastAttr = NULL; +} + +ZxElement::~ZxElement() { + delete type; + deleteGHash(attrs, ZxAttr); +} + +bool ZxElement::isElement(const char *typeA) { + return !type->cmp(typeA); +} + +ZxAttr *ZxElement::findAttr(const char *attrName) { + return (ZxAttr *)attrs->lookup(attrName); +} + +void ZxElement::addAttr(ZxAttr *attr) { + attrs->add(attr->getName(), attr); + if (lastAttr) { + lastAttr->next = attr; + lastAttr= attr; + } else { + firstAttr = lastAttr = attr; + } + attr->parent = this; + attr->next = NULL; +} + +bool ZxElement::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + ZxAttr *attr; + ZxNode *child; + bool ok; + + s = new GString("<"); + s->append(type); + for (attr = firstAttr; attr; attr = attr->getNextAttr()) { + s->append(" "); + s->append(attr->name); + s->append("=\""); + appendEscapedAttrValue(s, attr->value); + s->append("\""); + } + if ((child = getFirstChild())) { + s->append(">"); + } else { + s->append("/>"); + } + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + if (!ok) { + return false; + } + if (child) { + for (; child; child = child->getNextChild()) { + if (!child->write(writeFunc, stream)) { + return false; + } + } + s = new GString(); + s->append("</"); + s->append(type); + s->append(">"); + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + if (!ok) { + return false; + } + } + return true; +} + +void ZxElement::appendEscapedAttrValue(GString *out, GString *s) { + char c; + int i; + + for (i = 0; i < s->getLength(); ++i) { + c = s->getChar(i); + if (c == '<') { + out->append("<"); + } else if (c == '>') { + out->append(">"); + } else if (c == '&') { + out->append("&"); + } else if (c == '"') { + out->append("""); + } else { + out->append(c); + } + } +} + +//------------------------------------------------------------------------ + +ZxAttr::ZxAttr(GString *nameA, GString *valueA) { + name = nameA; + value = valueA; + parent = NULL; + next = NULL; +} + +ZxAttr::~ZxAttr() { + delete name; + delete value; +} + +//------------------------------------------------------------------------ + +ZxCharData::ZxCharData(GString *dataA, bool parsedA) { + data = dataA; + parsed = parsedA; +} + +ZxCharData::~ZxCharData() { + delete data; +} + +bool ZxCharData::write(ZxWriteFunc writeFunc, void *stream) { + GString *s; + char c; + int i; + bool ok; + + s = new GString(); + if (parsed) { + for (i = 0; i < data->getLength(); ++i) { + c = data->getChar(i); + if (c == '<') { + s->append("<"); + } else if (c == '>') { + s->append(">"); + } else if (c == '&') { + s->append("&"); + } else { + s->append(c); + } + } + } else { + s->append("<![CDATA["); + s->append(data); + s->append("]]>"); + } + ok = (*writeFunc)(stream, s->getCString(), s->getLength()); + delete s; + return ok; +} |