1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXMLWriter.h"
11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkStream.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLWriter::SkXMLWriter(bool doEscapeMarkup) : fDoEscapeMarkup(doEscapeMarkup)
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLWriter::~SkXMLWriter()
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(fElems.count() == 0);
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::flush()
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (fElems.count())
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->endElement();
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::addAttribute(const char name[], const char value[])
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->addAttributeLen(name, value, strlen(value));
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::addS32Attribute(const char name[], int32_t value)
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString    tmp;
36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.appendS32(value);
37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->addAttribute(name, tmp.c_str());
38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::addHexAttribute(const char name[], uint32_t value, int minDigits)
41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString    tmp("0x");
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.appendHex(value, minDigits);
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->addAttribute(name, tmp.c_str());
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::addScalarAttribute(const char name[], SkScalar value)
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString    tmp;
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tmp.appendScalar(value);
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->addAttribute(name, tmp.c_str());
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::doEnd(Elem* elem)
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    delete elem;
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkXMLWriter::doStart(const char name[], size_t length)
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int level = fElems.count();
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool firstChild = level > 0 && !fElems[level-1]->fHasChildren;
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (firstChild)
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fElems[level-1]->fHasChildren = true;
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Elem** elem = fElems.push();
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    *elem = new Elem;
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    (*elem)->fName.set(name, length);
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    (*elem)->fHasChildren = 0;
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return firstChild;
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
72dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.comSkXMLWriter::Elem* SkXMLWriter::getEnd()
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Elem* elem;
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fElems.pop(&elem);
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return elem;
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkXMLWriter::getHeader()
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static const char gHeader[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return gHeader;
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::startElement(const char name[])
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->startElementLen(name, strlen(name));
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic const char* escape_char(char c, char storage[2])
91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static const char* gEscapeChars[] = {
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        "<&lt;",
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        ">&gt;",
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        //"\"&quot;",
96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        //"'&apos;",
97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        "&&amp;"
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    };
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const char** array = gEscapeChars;
101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (unsigned i = 0; i < SK_ARRAY_COUNT(gEscapeChars); i++)
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (array[i][0] == c)
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return &array[i][1];
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    storage[0] = c;
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    storage[1] = 0;
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return storage;
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic size_t escape_markup(char dst[], const char src[], size_t length)
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    size_t      extra = 0;
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const char* stop = src + length;
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (src < stop)
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        char        orig[2];
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const char* seq = escape_char(*src, orig);
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        size_t      seqSize = strlen(seq);
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (dst)
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        {
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            memcpy(dst, seq, seqSize);
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            dst += seqSize;
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // now record the extra size needed
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        extra += seqSize - 1;   // minus one to subtract the original char
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // bump to the next src char
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        src += 1;
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return extra;
135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::addAttributeLen(const char name[], const char value[], size_t length)
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString valueStr;
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fDoEscapeMarkup)
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        size_t   extra = escape_markup(NULL, value, length);
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (extra)
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        {
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            valueStr.resize(length + extra);
147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            (void)escape_markup(valueStr.writable_str(), value, length);
148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            value = valueStr.c_str();
149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            length += extra;
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->onAddAttributeLen(name, value, length);
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::startElementLen(const char elem[], size_t length)
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->onStartElementLen(elem, length);
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////////
161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void write_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLWriter* w, bool skipRoot)
163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (!skipRoot)
165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w->startElement(dom.getName(node));
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkDOM::AttrIter iter(dom, node);
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const char* name;
170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const char* value;
171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        while ((name = iter.next(&value)) != NULL)
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w->addAttribute(name, value);
173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    node = dom.getFirstChild(node, NULL);
176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (node)
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        write_dom(dom, node, w, false);
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        node = dom.getNextSibling(node, NULL);
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (!skipRoot)
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w->endElement();
184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::writeDOM(const SkDOM& dom, const SkDOM::Node* node, bool skipRoot)
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (node)
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        write_dom(dom, node, this, skipRoot);
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLWriter::writeHeader()
193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// SkXMLStreamWriter
197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void tab(SkWStream& stream, int level)
199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int i = 0; i < level; i++)
201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        stream.writeText("\t");
202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLStreamWriter::SkXMLStreamWriter(SkWStream* stream) : fStream(*stream)
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLStreamWriter::~SkXMLStreamWriter()
209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->flush();
211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLStreamWriter::onAddAttributeLen(const char name[], const char value[], size_t length)
214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(!fElems.top()->fHasChildren);
216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.writeText(" ");
217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.writeText(name);
218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.writeText("=\"");
219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.write(value, length);
220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.writeText("\"");
221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLStreamWriter::onEndElement()
224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Elem* elem = getEnd();
226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (elem->fHasChildren)
227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        tab(fStream, fElems.count());
229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.writeText("</");
230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.writeText(elem->fName.c_str());
231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.writeText(">");
232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    else
234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.writeText("/>");
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.newline();
236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    doEnd(elem);
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLStreamWriter::onStartElementLen(const char name[], size_t length)
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int level = fElems.count();
242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (this->doStart(name, length))
243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // the first child, need to close with >
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.writeText(">");
246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fStream.newline();
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    tab(fStream, level);
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.writeText("<");
251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.write(name, length);
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLStreamWriter::writeHeader()
255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const char* header = getHeader();
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.write(header, strlen(header));
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fStream.newline();
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////////////////
262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXMLParser.h"
264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLParserWriter::SkXMLParserWriter(SkXMLParser* parser)
266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    : SkXMLWriter(false), fParser(*parser)
267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkXMLParserWriter::~SkXMLParserWriter()
271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->flush();
273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLParserWriter::onAddAttributeLen(const char name[], const char value[], size_t length)
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(fElems.count() == 0 || !fElems.top()->fHasChildren);
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString str(value, length);
279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fParser.addAttribute(name, str.c_str());
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLParserWriter::onEndElement()
283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Elem* elem = this->getEnd();
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fParser.endElement(elem->fName.c_str());
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->doEnd(elem);
287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLParserWriter::onStartElementLen(const char name[], size_t length)
290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    (void)this->doStart(name, length);
292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkString str(name, length);
293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fParser.startElement(str.c_str());
294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////////
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////////
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG
301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkXMLStreamWriter::UnitTest()
303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SUPPORT_UNITTEST
305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkDebugWStream  s;
306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkXMLStreamWriter       w(&s);
307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.startElement("elem0");
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.addAttribute("hello", "world");
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.addS32Attribute("dec", 42);
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.addHexAttribute("hex", 0x42, 3);
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.addScalarAttribute("scalar", -4.2f);
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.startElement("elem1");
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.endElement();
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.startElement("elem1");
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.addAttribute("name", "value");
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.endElement();
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.startElement("elem1");
321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w.startElement("elem2");
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                w.startElement("elem3");
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                w.addAttribute("name", "value");
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                w.endElement();
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w.endElement();
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w.startElement("elem2");
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            w.endElement();
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        w.endElement();
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    w.endElement();
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
334