
/*
 * 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 "SkXMLParser.h"
#include "SkChunkAlloc.h"
#include "SkString.h"
#include "SkStream.h"

#include "expat.h"

static inline char* dupstr(SkChunkAlloc& chunk, const char src[], size_t len)
{
    SkASSERT(src);
    char*   dst = (char*)chunk.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);

    memcpy(dst, src, len);
    dst[len] = 0;
    return dst;
}

static inline int count_pairs(const char** p)
{
    const char** start = p;
    while (*p)
    {
        SkASSERT(p[1] != NULL);
        p += 2;
    }
    return (p - start) >> 1;
}

struct Data {
    Data() : fAlloc(2048), fState(NORMAL) {}

    XML_Parser              fParser;
    SkXMLPullParser::Curr*  fCurr;
    SkChunkAlloc            fAlloc;

    enum State {
        NORMAL,
        MISSED_START_TAG,
        RETURN_END_TAG
    };
    State fState;
    const char* fEndTag;    // if state is RETURN_END_TAG
};

static void XMLCALL start_proc(void *data, const char *el, const char **attr)
{
    Data*                   p = (Data*)data;
    SkXMLPullParser::Curr*  c = p->fCurr;
    SkChunkAlloc&           alloc = p->fAlloc;

    c->fName = dupstr(alloc, el, strlen(el));

    int n = count_pairs(attr);
    SkXMLPullParser::AttrInfo* info = (SkXMLPullParser::AttrInfo*)alloc.alloc(n * sizeof(SkXMLPullParser::AttrInfo),
                                                                              SkChunkAlloc::kThrow_AllocFailType);
    c->fAttrInfoCount = n;
    c->fAttrInfos = info;

    for (int i = 0; i < n; i++)
    {
        info[i].fName = dupstr(alloc, attr[0], strlen(attr[0]));
        info[i].fValue = dupstr(alloc, attr[1], strlen(attr[1]));
        attr += 2;
    }

    c->fEventType = SkXMLPullParser::START_TAG;
    XML_StopParser(p->fParser, true);
}

static void XMLCALL end_proc(void *data, const char *el)
{
    Data*                   p = (Data*)data;
    SkXMLPullParser::Curr*  c = p->fCurr;

    if (c->fEventType == SkXMLPullParser::START_TAG)
    {
        /*  if we get here, we were called with a start_tag immediately
            followed by this end_tag. The caller will only see the end_tag,
            so we set a flag to notify them of the missed start_tag
        */
        p->fState = Data::MISSED_START_TAG;

        SkASSERT(c->fName != NULL);
        SkASSERT(strcmp(c->fName, el) == 0);
    }
    else
        c->fName = dupstr(p->fAlloc, el, strlen(el));

    c->fEventType = SkXMLPullParser::END_TAG;
    XML_StopParser(p->fParser, true);
}

#include <ctype.h>

static bool isws(const char s[])
{
    for (; *s; s++)
        if (!isspace(*s))
            return false;
    return true;
}

static void XMLCALL text_proc(void* data, const char* text, int len)
{
    Data*                   p = (Data*)data;
    SkXMLPullParser::Curr*  c = p->fCurr;

    c->fName = dupstr(p->fAlloc, text, len);
    c->fIsWhitespace = isws(c->fName);

    c->fEventType = SkXMLPullParser::TEXT;
    XML_StopParser(p->fParser, true);
}

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

struct SkXMLPullParser::Impl {
    Data    fData;
    void*   fBuffer;
    size_t  fBufferLen;
};

static void reportError(XML_Parser parser)
{
    XML_Error code = XML_GetErrorCode(parser);
    int lineNumber = XML_GetCurrentLineNumber(parser);
    const char* msg = XML_ErrorString(code);

    printf("-------- XML error [%d] on line %d, %s\n", code, lineNumber, msg);
}

bool SkXMLPullParser::onInit()
{
    fImpl = new Impl;

    XML_Parser p = XML_ParserCreate(NULL);
    SkASSERT(p);

    fImpl->fData.fParser = p;
    fImpl->fData.fCurr = &fCurr;

    XML_SetElementHandler(p, start_proc, end_proc);
    XML_SetCharacterDataHandler(p, text_proc);
    XML_SetUserData(p, &fImpl->fData);

    size_t len = fStream->getLength();
    fImpl->fBufferLen = len;
    fImpl->fBuffer = sk_malloc_throw(len);
    fStream->rewind();
    size_t  len2 = fStream->read(fImpl->fBuffer, len);
    return len2 == len;
}

void SkXMLPullParser::onExit()
{
    sk_free(fImpl->fBuffer);
    XML_ParserFree(fImpl->fData.fParser);
    delete fImpl;
    fImpl = NULL;
}

SkXMLPullParser::EventType SkXMLPullParser::onNextToken()
{
    if (Data::RETURN_END_TAG == fImpl->fData.fState)
    {
        fImpl->fData.fState = Data::NORMAL;
        fCurr.fName = fImpl->fData.fEndTag; // restore name from (below) save
        return SkXMLPullParser::END_TAG;
    }

    fImpl->fData.fAlloc.reset();

    XML_Parser p = fImpl->fData.fParser;
    XML_Status status;

    status = XML_ResumeParser(p);

CHECK_STATUS:
    switch (status) {
    case XML_STATUS_OK:
        return SkXMLPullParser::END_DOCUMENT;

    case XML_STATUS_ERROR:
        if (XML_GetErrorCode(p) != XML_ERROR_NOT_SUSPENDED)
        {
            reportError(p);
            return SkXMLPullParser::ERROR;
        }
        status = XML_Parse(p, (const char*)fImpl->fBuffer, fImpl->fBufferLen, true);
        goto CHECK_STATUS;

    case XML_STATUS_SUSPENDED:
        if (Data::MISSED_START_TAG == fImpl->fData.fState)
        {
            // return a start_tag, and clear the flag so we return end_tag next
            SkASSERT(SkXMLPullParser::END_TAG == fCurr.fEventType);
            fImpl->fData.fState = Data::RETURN_END_TAG;
            fImpl->fData.fEndTag = fCurr.fName;  // save this pointer
            return SkXMLPullParser::START_TAG;
        }
        break;
    }
    return fCurr.fEventType;
}
