/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef jsonparser_h
#define jsonparser_h

#include "mozilla/Attributes.h"

#include "jsapi.h"

#include "vm/String.h"

namespace js {

class MOZ_STACK_CLASS JSONParser : private AutoGCRooter
{
  public:
    enum ErrorHandling { RaiseError, NoError };

  private:
    /* Data members */

    JSContext * const cx;
    StableCharPtr current;
    const StableCharPtr end;

    Value v;

    const ErrorHandling errorHandling;

    enum Token { String, Number, True, False, Null,
                 ArrayOpen, ArrayClose,
                 ObjectOpen, ObjectClose,
                 Colon, Comma,
                 OOM, Error };

    // State related to the parser's current position. At all points in the
    // parse this keeps track of the stack of arrays and objects which have
    // been started but not finished yet. The actual JS object is not
    // allocated until the literal is closed, so that the result can be sized
    // according to its contents and have its type and shape filled in using
    // caches.

    // State for an array that is currently being parsed. This includes all
    // elements that have been seen so far.
    typedef Vector<Value, 20> ElementVector;

    // State for an object that is currently being parsed. This includes all
    // the key/value pairs that have been seen so far.
    typedef Vector<IdValuePair, 10> PropertyVector;

    // Possible states the parser can be in between values.
    enum ParserState {
        // An array element has just being parsed.
        FinishArrayElement,

        // An object property has just been parsed.
        FinishObjectMember,

        // At the start of the parse, before any values have been processed.
        JSONValue
    };

    // Stack element for an in progress array or object.
    struct StackEntry {
        ElementVector &elements() {
            JS_ASSERT(state == FinishArrayElement);
            return * static_cast<ElementVector *>(vector);
        }

        PropertyVector &properties() {
            JS_ASSERT(state == FinishObjectMember);
            return * static_cast<PropertyVector *>(vector);
        }

        StackEntry(ElementVector *elements)
          : state(FinishArrayElement), vector(elements)
        {}

        StackEntry(PropertyVector *properties)
          : state(FinishObjectMember), vector(properties)
        {}

        ParserState state;

      private:
        void *vector;
    };

    // All in progress arrays and objects being parsed, in order from outermost
    // to innermost.
    Vector<StackEntry, 10> stack;

    // Unused element and property vectors for previous in progress arrays and
    // objects. These vectors are not freed until the end of the parse to avoid
    // unnecessary freeing and allocation.
    Vector<ElementVector*, 5> freeElements;
    Vector<PropertyVector*, 5> freeProperties;

#ifdef DEBUG
    Token lastToken;
#endif

    JSONParser *thisDuringConstruction() { return this; }

  public:
    /* Public API */

    /* Create a parser for the provided JSON data. */
    JSONParser(JSContext *cx, JS::StableCharPtr data, size_t length,
               ErrorHandling errorHandling = RaiseError)
      : AutoGCRooter(cx, JSONPARSER),
        cx(cx),
        current(data),
        end((data + length).get(), data.get(), length),
        errorHandling(errorHandling),
        stack(cx),
        freeElements(cx),
        freeProperties(cx)
#ifdef DEBUG
      , lastToken(Error)
#endif
    {
        JS_ASSERT(current <= end);
    }

    ~JSONParser();

    /*
     * Parse the JSON data specified at construction time.  If it parses
     * successfully, store the prescribed value in *vp and return true.  If an
     * internal error (e.g. OOM) occurs during parsing, return false.
     * Otherwise, if invalid input was specifed but no internal error occurred,
     * behavior depends upon the error handling specified at construction: if
     * error handling is RaiseError then throw a SyntaxError and return false,
     * otherwise return true and set *vp to |undefined|.  (JSON syntax can't
     * represent |undefined|, so the JSON data couldn't have specified it.)
     */
    bool parse(MutableHandleValue vp);

  private:
    Value numberValue() const {
        JS_ASSERT(lastToken == Number);
        JS_ASSERT(v.isNumber());
        return v;
    }

    Value stringValue() const {
        JS_ASSERT(lastToken == String);
        JS_ASSERT(v.isString());
        return v;
    }

    JSAtom *atomValue() const {
        Value strval = stringValue();
        return &strval.toString()->asAtom();
    }

    Token token(Token t) {
        JS_ASSERT(t != String);
        JS_ASSERT(t != Number);
#ifdef DEBUG
        lastToken = t;
#endif
        return t;
    }

    Token stringToken(JSString *str) {
        this->v = StringValue(str);
#ifdef DEBUG
        lastToken = String;
#endif
        return String;
    }

    Token numberToken(double d) {
        this->v = NumberValue(d);
#ifdef DEBUG
        lastToken = Number;
#endif
        return Number;
    }

    enum StringType { PropertyName, LiteralValue };
    template<StringType ST> Token readString();

    Token readNumber();

    Token advance();
    Token advancePropertyName();
    Token advancePropertyColon();
    Token advanceAfterProperty();
    Token advanceAfterObjectOpen();
    Token advanceAfterArrayElement();

    void error(const char *msg);
    bool errorReturn();

    JSObject *createFinishedObject(PropertyVector &properties);
    bool finishObject(MutableHandleValue vp, PropertyVector &properties);
    bool finishArray(MutableHandleValue vp, ElementVector &elements);

    friend void AutoGCRooter::trace(JSTracer *trc);
    void trace(JSTracer *trc);

  private:
    JSONParser(const JSONParser &other) MOZ_DELETE;
    void operator=(const JSONParser &other) MOZ_DELETE;
};

} /* namespace js */

#endif /* jsonparser_h */
