1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXMLWriter.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLWriter::SkXMLWriter(bool doEscapeMarkup) : fDoEscapeMarkup(doEscapeMarkup)
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLWriter::~SkXMLWriter()
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fElems.count() == 0);
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::flush()
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (fElems.count())
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->endElement();
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::addAttribute(const char name[], const char value[])
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->addAttributeLen(name, value, strlen(value));
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::addS32Attribute(const char name[], int32_t value)
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendS32(value);
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->addAttribute(name, tmp.c_str());
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::addHexAttribute(const char name[], uint32_t value, int minDigits)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp("0x");
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendHex(value, minDigits);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->addAttribute(name, tmp.c_str());
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::addScalarAttribute(const char name[], SkScalar value)
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendScalar(value);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->addAttribute(name, tmp.c_str());
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::doEnd(Elem* elem)
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    delete elem;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkXMLWriter::doStart(const char name[], size_t length)
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int level = fElems.count();
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool firstChild = level > 0 && !fElems[level-1]->fHasChildren;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (firstChild)
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fElems[level-1]->fHasChildren = true;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Elem** elem = fElems.push();
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *elem = new Elem;
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (*elem)->fName.set(name, length);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (*elem)->fHasChildren = 0;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return firstChild;
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkXMLWriter::Elem* SkXMLWriter::getEnd()
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Elem* elem;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fElems.pop(&elem);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return elem;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkXMLWriter::getHeader()
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const char gHeader[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gHeader;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::startElement(const char name[])
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->startElementLen(name, strlen(name));
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const char* escape_char(char c, char storage[2])
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const char* gEscapeChars[] = {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        "<&lt;",
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ">&gt;",
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        //"\"&quot;",
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        //"'&apos;",
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        "&&amp;"
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char** array = gEscapeChars;
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (unsigned i = 0; i < SK_ARRAY_COUNT(gEscapeChars); i++)
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (array[i][0] == c)
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return &array[i][1];
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    storage[0] = c;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    storage[1] = 0;
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return storage;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic size_t escape_markup(char dst[], const char src[], size_t length)
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t      extra = 0;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = src + length;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (src < stop)
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        char        orig[2];
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const char* seq = escape_char(*src, orig);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t      seqSize = strlen(seq);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (dst)
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(dst, seq, seqSize);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += seqSize;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now record the extra size needed
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        extra += seqSize - 1;   // minus one to subtract the original char
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // bump to the next src char
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += 1;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return extra;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::addAttributeLen(const char name[], const char value[], size_t length)
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString valueStr;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDoEscapeMarkup)
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t   extra = escape_markup(NULL, value, length);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (extra)
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            valueStr.resize(length + extra);
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (void)escape_markup(valueStr.writable_str(), value, length);
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value = valueStr.c_str();
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            length += extra;
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->onAddAttributeLen(name, value, length);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::startElementLen(const char elem[], size_t length)
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->onStartElementLen(elem, length);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void write_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLWriter* w, bool skipRoot)
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!skipRoot)
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w->startElement(dom.getName(node));
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDOM::AttrIter iter(dom, node);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const char* name;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const char* value;
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while ((name = iter.next(&value)) != NULL)
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            w->addAttribute(name, value);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    node = dom.getFirstChild(node, NULL);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (node)
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        write_dom(dom, node, w, false);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        node = dom.getNextSibling(node, NULL);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!skipRoot)
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w->endElement();
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::writeDOM(const SkDOM& dom, const SkDOM::Node* node, bool skipRoot)
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (node)
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        write_dom(dom, node, this, skipRoot);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLWriter::writeHeader()
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkXMLStreamWriter
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void tab(SkWStream& stream, int level)
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = 0; i < level; i++)
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        stream.writeText("\t");
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLStreamWriter::SkXMLStreamWriter(SkWStream* stream) : fStream(*stream)
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLStreamWriter::~SkXMLStreamWriter()
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->flush();
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLStreamWriter::onAddAttributeLen(const char name[], const char value[], size_t length)
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(!fElems.top()->fHasChildren);
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.writeText(" ");
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.writeText(name);
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.writeText("=\"");
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.write(value, length);
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.writeText("\"");
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLStreamWriter::onEndElement()
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Elem* elem = getEnd();
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (elem->fHasChildren)
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tab(fStream, fElems.count());
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.writeText("</");
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.writeText(elem->fName.c_str());
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.writeText(">");
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.writeText("/>");
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.newline();
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    doEnd(elem);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLStreamWriter::onStartElementLen(const char name[], size_t length)
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int level = fElems.count();
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->doStart(name, length))
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // the first child, need to close with >
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.writeText(">");
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStream.newline();
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tab(fStream, level);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.writeText("<");
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.write(name, length);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLStreamWriter::writeHeader()
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* header = getHeader();
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.write(header, strlen(header));
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStream.newline();
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////////
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXMLParser.h"
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLParserWriter::SkXMLParserWriter(SkXMLParser* parser)
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : SkXMLWriter(false), fParser(*parser)
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkXMLParserWriter::~SkXMLParserWriter()
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->flush();
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLParserWriter::onAddAttributeLen(const char name[], const char value[], size_t length)
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fElems.count() == 0 || !fElems.top()->fHasChildren);
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString str(value, length);
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fParser.addAttribute(name, str.c_str());
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLParserWriter::onEndElement()
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Elem* elem = this->getEnd();
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fParser.endElement(elem->fName.c_str());
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->doEnd(elem);
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLParserWriter::onStartElementLen(const char name[], size_t length)
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)this->doStart(name, length);
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString str(name, length);
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fParser.startElement(str.c_str());
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkXMLStreamWriter::UnitTest()
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SUPPORT_UNITTEST
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDebugWStream  s;
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXMLStreamWriter       w(&s);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.startElement("elem0");
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.addAttribute("hello", "world");
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.addS32Attribute("dec", 42);
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.addHexAttribute("hex", 0x42, 3);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.addScalarAttribute("scalar", -4.2f);
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.startElement("elem1");
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.endElement();
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.startElement("elem1");
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.addAttribute("name", "value");
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.endElement();
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.startElement("elem1");
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            w.startElement("elem2");
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                w.startElement("elem3");
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                w.addAttribute("name", "value");
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                w.endElement();
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            w.endElement();
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            w.startElement("elem2");
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            w.endElement();
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        w.endElement();
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    w.endElement();
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
332