/*
 * 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 "src/xml/SkXMLParser.h"

#include "expat.h"

#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTo.h"

static char const* const gErrorStrings[] = {
    "empty or missing file ",
    "unknown element ",
    "unknown attribute name ",
    "error in attribute value ",
    "duplicate ID ",
    "unknown error "
};

SkXMLParserError::SkXMLParserError() : fCode(kNoError), fLineNumber(-1),
    fNativeCode(-1)
{
    reset();
}

SkXMLParserError::~SkXMLParserError()
{
    // need a virtual destructor for our subclasses
}

void SkXMLParserError::getErrorString(SkString* str) const
{
    SkASSERT(str);
    SkString temp;
    if (fCode != kNoError) {
        if ((unsigned)fCode < SK_ARRAY_COUNT(gErrorStrings))
            temp.set(gErrorStrings[fCode - 1]);
        temp.append(fNoun);
    } else
        SkXMLParser::GetNativeErrorString(fNativeCode, &temp);
    str->append(temp);
}

void SkXMLParserError::reset() {
    fCode = kNoError;
    fLineNumber = -1;
    fNativeCode = -1;
}

////////////////

namespace {

const XML_Memory_Handling_Suite sk_XML_alloc = {
    sk_malloc_throw,
    sk_realloc_throw,
    sk_free
};

struct ParsingContext {
    ParsingContext(SkXMLParser* parser)
        : fParser(parser)
        , fXMLParser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)) { }

    void flushText() {
        if (!fBufferedText.isEmpty()) {
            fParser->text(fBufferedText.c_str(), SkTo<int>(fBufferedText.size()));
            fBufferedText.reset();
        }
    }

    void appendText(const char* txt, size_t len) {
        fBufferedText.append(txt, len);
    }

    SkXMLParser* fParser;
    SkAutoTCallVProc<std::remove_pointer_t<XML_Parser>, XML_ParserFree> fXMLParser;

private:
    SkString fBufferedText;
};

#define HANDLER_CONTEXT(arg, name) ParsingContext* name = static_cast<ParsingContext*>(arg)

void XMLCALL start_element_handler(void *data, const char* tag, const char** attributes) {
    HANDLER_CONTEXT(data, ctx);
    ctx->flushText();

    ctx->fParser->startElement(tag);

    for (size_t i = 0; attributes[i]; i += 2) {
        ctx->fParser->addAttribute(attributes[i], attributes[i + 1]);
    }
}

void XMLCALL end_element_handler(void* data, const char* tag) {
    HANDLER_CONTEXT(data, ctx);
    ctx->flushText();

    ctx->fParser->endElement(tag);
}

void XMLCALL text_handler(void *data, const char* txt, int len) {
    HANDLER_CONTEXT(data, ctx);

    ctx->appendText(txt, SkTo<size_t>(len));
}

void XMLCALL entity_decl_handler(void *data,
                                 const XML_Char *entityName,
                                 int is_parameter_entity,
                                 const XML_Char *value,
                                 int value_length,
                                 const XML_Char *base,
                                 const XML_Char *systemId,
                                 const XML_Char *publicId,
                                 const XML_Char *notationName) {
    HANDLER_CONTEXT(data, ctx);

    SkDebugf("'%s' entity declaration found, stopping processing", entityName);
    XML_StopParser(ctx->fXMLParser, XML_FALSE);
}

} // anonymous namespace

SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fError(parserError)
{
}

SkXMLParser::~SkXMLParser()
{
}

bool SkXMLParser::parse(SkStream& docStream)
{
    ParsingContext ctx(this);
    if (!ctx.fXMLParser) {
        SkDebugf("could not create XML parser\n");
        return false;
    }

    XML_SetUserData(ctx.fXMLParser, &ctx);
    XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_handler);
    XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler);

    // Disable entity processing, to inhibit internal entity expansion. See expat CVE-2013-0340.
    XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler);

    static const int kBufferSize = 512 SkDEBUGCODE( - 507);
    bool done = false;
    do {
        void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize);
        if (!buffer) {
            SkDebugf("could not buffer enough to continue\n");
            return false;
        }

        size_t len = docStream.read(buffer, kBufferSize);
        done = docStream.isAtEnd();
        XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done);
        if (XML_STATUS_ERROR == status) {
            XML_Error error = XML_GetErrorCode(ctx.fXMLParser);
            int line = XML_GetCurrentLineNumber(ctx.fXMLParser);
            int column = XML_GetCurrentColumnNumber(ctx.fXMLParser);
            const XML_LChar* errorString = XML_ErrorString(error);
            SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, errorString);
            return false;
        }
    } while (!done);

    return true;
}

bool SkXMLParser::parse(const char doc[], size_t len)
{
    SkMemoryStream docStream(doc, len);
    return this->parse(docStream);
}

void SkXMLParser::GetNativeErrorString(int error, SkString* str)
{

}

bool SkXMLParser::startElement(const char elem[])
{
    return this->onStartElement(elem);
}

bool SkXMLParser::addAttribute(const char name[], const char value[])
{
    return this->onAddAttribute(name, value);
}

bool SkXMLParser::endElement(const char elem[])
{
    return this->onEndElement(elem);
}

bool SkXMLParser::text(const char text[], int len)
{
    return this->onText(text, len);
}

////////////////////////////////////////////////////////////////////////////////

bool SkXMLParser::onStartElement(const char elem[]) {return false; }
bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; }
bool SkXMLParser::onEndElement(const char elem[]) { return false; }
bool SkXMLParser::onText(const char text[], int len) {return false; }
