/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#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::addText(const char text[], size_t length) {
    if (fElems.isEmpty()) {
        return;
    }
    
    this->onAddText(text, length);
    
    fElems.top()->fHasText = true;
}

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(name, length);
    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[] = {
        "<&lt;",
        ">&gt;",
        //"\"&quot;",
        //"'&apos;",
        "&&amp;"
    };

    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(nullptr, 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) {
        const char* elem = dom.getName(node);
        if (dom.getType(node) == SkDOM::kText_Type) {
            SkASSERT(dom.countChildren(node) == 0);
            w->addText(elem, strlen(elem));
            return;
        }

        w->startElement(elem);

        SkDOM::AttrIter iter(dom, node);
        const char* name;
        const char* value;
        while ((name = iter.next(&value)) != nullptr) {
            w->addAttribute(name, value);
        }
    }

    node = dom.getFirstChild(node, nullptr);
    while (node) {
        write_dom(dom, node, w, false);
        node = dom.getNextSibling(node, nullptr);
    }

    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 && !fElems.top()->fHasText);
    fStream.writeText(" ");
    fStream.writeText(name);
    fStream.writeText("=\"");
    fStream.write(value, length);
    fStream.writeText("\"");
}

void SkXMLStreamWriter::onAddText(const char text[], size_t length) {
    Elem* elem = fElems.top();

    if (!elem->fHasChildren && !elem->fHasText) {
        fStream.writeText(">");
        fStream.newline();
    }

    tab(fStream, fElems.count() + 1);
    fStream.write(text, length);
    fStream.newline();
}

void SkXMLStreamWriter::onEndElement() {
    Elem* elem = getEnd();
    if (elem->fHasChildren || elem->fHasText) {
        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 && !fElems.top()->fHasText));
    SkString str(value, length);
    fParser.addAttribute(name, str.c_str());
}

void SkXMLParserWriter::onAddText(const char text[], size_t length) {
    fParser.text(text, SkToInt(length));
}

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());
}
