diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/xml/SkXMLWriter.cpp | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2 |
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/xml/SkXMLWriter.cpp')
-rw-r--r-- | skia/xml/SkXMLWriter.cpp | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/skia/xml/SkXMLWriter.cpp b/skia/xml/SkXMLWriter.cpp new file mode 100644 index 0000000..e8df912 --- /dev/null +++ b/skia/xml/SkXMLWriter.cpp @@ -0,0 +1,342 @@ +/* libs/graphics/xml/SkXMLWriter.cpp +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkXMLWriter.h" +#include "SkStream.h" + +SkXMLWriter::SkXMLWriter(bool doEscapeMarkup) : fDoEscapeMarkup(doEscapeMarkup) +{ +} + +SkXMLWriter::~SkXMLWriter() +{ + SkASSERT(fElems.count() == 0); +} + +void SkXMLWriter::flush() +{ + while (fElems.count()) + this->endElement(); +} + +void SkXMLWriter::addAttribute(const char name[], const char value[]) +{ + this->addAttributeLen(name, value, strlen(value)); +} + +void SkXMLWriter::addS32Attribute(const char name[], int32_t value) +{ + SkString tmp; + tmp.appendS32(value); + this->addAttribute(name, tmp.c_str()); +} + +void SkXMLWriter::addHexAttribute(const char name[], uint32_t value, int minDigits) +{ + SkString tmp("0x"); + tmp.appendHex(value, minDigits); + this->addAttribute(name, tmp.c_str()); +} + +void SkXMLWriter::addScalarAttribute(const char name[], SkScalar value) +{ + SkString tmp; + tmp.appendScalar(value); + this->addAttribute(name, tmp.c_str()); +} + +void SkXMLWriter::doEnd(Elem* elem) +{ + delete elem; +} + +bool SkXMLWriter::doStart(const char name[], size_t length) +{ + int level = fElems.count(); + bool firstChild = level > 0 && !fElems[level-1]->fHasChildren; + if (firstChild) + fElems[level-1]->fHasChildren = true; + Elem** elem = fElems.push(); + *elem = new Elem; + (*elem)->fName.set(name, length); + (*elem)->fHasChildren = 0; + return firstChild; +} + +SkXMLWriter::Elem* SkXMLWriter::getEnd() +{ + Elem* elem; + fElems.pop(&elem); + return elem; +} + +const char* SkXMLWriter::getHeader() +{ + static const char gHeader[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"; + return gHeader; +} + +void SkXMLWriter::startElement(const char name[]) +{ + this->startElementLen(name, strlen(name)); +} + +static const char* escape_char(char c, char storage[2]) +{ + static const char* gEscapeChars[] = { + "<<", + ">>", + //"\""", + //"''", + "&&" + }; + + const char** array = gEscapeChars; + for (unsigned i = 0; i < SK_ARRAY_COUNT(gEscapeChars); i++) + { + if (array[i][0] == c) + return &array[i][1]; + } + storage[0] = c; + storage[1] = 0; + return storage; +} + +static size_t escape_markup(char dst[], const char src[], size_t length) +{ + size_t extra = 0; + const char* stop = src + length; + + while (src < stop) + { + char orig[2]; + const char* seq = escape_char(*src, orig); + size_t seqSize = strlen(seq); + + if (dst) + { + memcpy(dst, seq, seqSize); + dst += seqSize; + } + + // now record the extra size needed + extra += seqSize - 1; // minus one to subtract the original char + + // bump to the next src char + src += 1; + } + return extra; +} + +void SkXMLWriter::addAttributeLen(const char name[], const char value[], size_t length) +{ + SkString valueStr; + + if (fDoEscapeMarkup) + { + size_t extra = escape_markup(NULL, value, length); + if (extra) + { + valueStr.resize(length + extra); + (void)escape_markup(valueStr.writable_str(), value, length); + value = valueStr.c_str(); + length += extra; + } + } + this->onAddAttributeLen(name, value, length); +} + +void SkXMLWriter::startElementLen(const char elem[], size_t length) +{ + this->onStartElementLen(elem, length); +} + +//////////////////////////////////////////////////////////////////////////////////////// + +static void write_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLWriter* w, bool skipRoot) +{ + if (!skipRoot) + { + w->startElement(dom.getName(node)); + + SkDOM::AttrIter iter(dom, node); + const char* name; + const char* value; + while ((name = iter.next(&value)) != NULL) + w->addAttribute(name, value); + } + + node = dom.getFirstChild(node, NULL); + while (node) + { + write_dom(dom, node, w, false); + node = dom.getNextSibling(node, NULL); + } + + if (!skipRoot) + w->endElement(); +} + +void SkXMLWriter::writeDOM(const SkDOM& dom, const SkDOM::Node* node, bool skipRoot) +{ + if (node) + write_dom(dom, node, this, skipRoot); +} + +void SkXMLWriter::writeHeader() +{ +} + +// SkXMLStreamWriter + +static void tab(SkWStream& stream, int level) +{ + for (int i = 0; i < level; i++) + stream.writeText("\t"); +} + +SkXMLStreamWriter::SkXMLStreamWriter(SkWStream* stream) : fStream(*stream) +{ +} + +SkXMLStreamWriter::~SkXMLStreamWriter() +{ + this->flush(); +} + +void SkXMLStreamWriter::onAddAttributeLen(const char name[], const char value[], size_t length) +{ + SkASSERT(!fElems.top()->fHasChildren); + fStream.writeText(" "); + fStream.writeText(name); + fStream.writeText("=\""); + fStream.write(value, length); + fStream.writeText("\""); +} + +void SkXMLStreamWriter::onEndElement() +{ + Elem* elem = getEnd(); + if (elem->fHasChildren) + { + tab(fStream, fElems.count()); + fStream.writeText("</"); + fStream.writeText(elem->fName.c_str()); + fStream.writeText(">"); + } + else + fStream.writeText("/>"); + fStream.newline(); + doEnd(elem); +} + +void SkXMLStreamWriter::onStartElementLen(const char name[], size_t length) +{ + int level = fElems.count(); + if (this->doStart(name, length)) + { + // the first child, need to close with > + fStream.writeText(">"); + fStream.newline(); + } + + tab(fStream, level); + fStream.writeText("<"); + fStream.write(name, length); +} + +void SkXMLStreamWriter::writeHeader() +{ + const char* header = getHeader(); + fStream.write(header, strlen(header)); + fStream.newline(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +#include "SkXMLParser.h" + +SkXMLParserWriter::SkXMLParserWriter(SkXMLParser* parser) + : SkXMLWriter(false), fParser(*parser) +{ +} + +SkXMLParserWriter::~SkXMLParserWriter() +{ + this->flush(); +} + +void SkXMLParserWriter::onAddAttributeLen(const char name[], const char value[], size_t length) +{ + SkASSERT(fElems.count() == 0 || !fElems.top()->fHasChildren); + SkString str(value, length); + fParser.addAttribute(name, str.c_str()); +} + +void SkXMLParserWriter::onEndElement() +{ + Elem* elem = this->getEnd(); + fParser.endElement(elem->fName.c_str()); + this->doEnd(elem); +} + +void SkXMLParserWriter::onStartElementLen(const char name[], size_t length) +{ + (void)this->doStart(name, length); + SkString str(name, length); + fParser.startElement(str.c_str()); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +void SkXMLStreamWriter::UnitTest() +{ +#ifdef SK_SUPPORT_UNITTEST + SkDebugWStream s; + SkXMLStreamWriter w(&s); + + w.startElement("elem0"); + w.addAttribute("hello", "world"); + w.addS32Attribute("dec", 42); + w.addHexAttribute("hex", 0x42, 3); +#ifdef SK_SCALAR_IS_FLOAT + w.addScalarAttribute("scalar", -4.2f); +#endif + w.startElement("elem1"); + w.endElement(); + w.startElement("elem1"); + w.addAttribute("name", "value"); + w.endElement(); + w.startElement("elem1"); + w.startElement("elem2"); + w.startElement("elem3"); + w.addAttribute("name", "value"); + w.endElement(); + w.endElement(); + w.startElement("elem2"); + w.endElement(); + w.endElement(); + w.endElement(); +#endif +} + +#endif + |