/*
 * ************************************************************************************************************
 * Author: Marcin Załęczny
 * Copyright (C)2010 Marcin Załęczny <mzaleczny@hotmail.com>
 * License: The GNU Lesser General Public License, version 3.0 (LGPLv3)
 * Library Name: mzstd
 * Version: 1.07
 * First release date:   2010-11-08
 * Current release date: 2011-03-04
 *
 *
 * This file is part of mzstd library
 * 
 * mzstd library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * mzstd library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * ************************************************************************************************************
 */

#ifndef __MZSTD_JSON_PARSER_H__
#define __MZSTD_JSON_PARSER_H__

#include "mzstdCommon.h"
#include "mzObject.h"
#include "mzString.h"
#include "mzStdObject.h"

#define     CJSONPARSER_GROW_CHUNK                                                  8192

#define     CJSONPARSER_STATE_EXPECT_OBJECT_OR_ARRAY                                1
#define     CJSONPARSER_STATE_EXPECT_OBJECT_OR_ARRAY_OR_VALUE_IN_ARRAY              2
#define     CJSONPARSER_STATE_EXPECT_ARRAY_VALUE_IN_DOUBLE_QUOTE                    3
#define     CJSONPARSER_STATE_EXPECT_ARRAY_VALUE_IN_SINGLE_QUOTE                    4
#define     CJSONPARSER_STATE_EXPECT_COMMA_OR_CLOSE_CURLY_BRACE                     5
#define     CJSONPARSER_STATE_EXPECT_COMMA_OR_CLOSE_SQUARE_BRACE                    6
#define     CJSONPARSER_STATE_EXPECT_OBJECT_PROPERTY_NAME                           7
#define     CJSONPARSER_STATE_EXPECT_OBJECT_SEMICOLON                               8
#define     CJSONPARSER_STATE_EXPECT_OBJECT_PROPERTY_VALUE                          9
#define     CJSONPARSER_STATE_EXPECT_OBJECT_VALUE_IN_DOUBLE_QUOTE                   10
#define     CJSONPARSER_STATE_EXPECT_OBJECT_VALUE_IN_SINGLE_QUOTE                   11
#define     CJSONPARSER_STATE_STOP_PARSING                                          100

#define     CJSONPARSER_CURRENT_ITEM_UNDEFINED                                      0
#define     CJSONPARSER_CURRENT_ITEM_ARRAY                                          1
#define     CJSONPARSER_CURRENT_ITEM_OBJECT                                         2

class CJsonParserEntity : public CObject {
public:
    WINAPI CJsonParserEntity(VOID *entity, LONG entity_type) {
        this->entity = entity;
        this->entity_type = entity_type;
    };
    // wskaźnik na obiekt
    VOID *entity;
    // typ obiektu:
    //  0 - nieokreślony
    //  1 - tablica (CArrayList)
    //  2 - obiekt  (CStdObject)
    LONG entity_type;
private:
    WINAPI CJsonParserEntity() {};
};
typedef CJsonParserEntity* PJsonParserEntity;

class DECLSPEC_MZSTD CJsonParser : public CObject {
public:
    WINAPI CJsonParser();
    virtual WINAPI ~CJsonParser();

    CStdObject* WINAPI parseFile(CString fname, CStdObject* destination = NULL);
    CStdObject* WINAPI parse(CString content, CStdObject* destination = NULL);
    inline BOOL WINAPI isError() {return this->_error != 0; };
    inline CString WINAPI getErrorMessage() {return this->_error_msg; };

private:
    // poniższy atrybut przechowuje obiekt który zostanie zwrócony po
    // poprawnym przeparsowaniu pliku json. Ma on jeden atrybut: 'root'
    // który zawiera wskaźnik na pierwszy obiekt lub tablicę w pliku
    // json.
    CStdObject *_retval;
    // Flag marking if retval object was created in CParser object or if it was supplied from parser caller.
    // If it was created inside parser, then if parser error this object is deleted. Otherwise not.
    BOOL _retvalInternalCreated;
    
    // tablica zawierająca wskaźniki na aktualnie przetwarzane encje.
    // są to wskaźniki na obiekty klasy CJsonParserEntity.
    CArrayList *_current_object;
    // nazwa atrybutu pod jaką zostanie dodana nowa wartość do
    // aktualnie przetwarzanego obiektu
    CString _current_object_attribute_name;

    CHAR *_current_token;
    LONG _current_token_buf_size;
    // ilość znaczących znaków w buforze tokena
    LONG _current_token_length;

    // Tablica kolejnych stanów parsera. Zawiera liczby całkowite.
    CArrayList *_current_state;
    // poniższa zmienna informuje czy nazwę atrybutu obiektu otoczono
    // cudzysłowem czy nie a jeśli tak, to jakim. Możliwe wartości:
    //  - - nazwa atrybutu podana bez cudzysłowu
    //  ' - nazwa atrybutu podana w pojedyńczym cudzysłowiu
    //  " - nazwa atrybutu podana w podwójnym cudzysłowiu
    CHAR _object_property_name_quote;

    LONG _error;
    CString _error_msg;
    DWORD _line_number;
    LONG _char_number_in_line;
    LONG _char_number_in_file;

    VOID WINAPI _processBuffer(CHAR *buf, DWORD buf_len);
    inline BOOL WINAPI _isWhiteSpace(CHAR ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; };
    VOID WINAPI _deleteCurrentObjectArray();
    VOID WINAPI _deleteCurrentStateArray();
    VOID WINAPI _cleanRetvalObject();
    CString WINAPI _getStringFromCurrentToken();
    VOID WINAPI _onExpectArrayValueInQuote(CHAR quoteType, CHAR ch);
    VOID WINAPI _onExpectObjectValueInQuote(CHAR quoteType, CHAR ch);
    VOID WINAPI _onBeginArray();
    VOID WINAPI _onBeginObject();
    VOID WINAPI _onCompleteReadObjectAttributeName();
    VOID WINAPI _onCompleteReadObjectAttributeSimpleValue();
    VOID WINAPI _appendCharToCurrentToken(CHAR ch);
    VOID WINAPI _onCloseSquare();
    VOID WINAPI _initParsingProcess(CStdObject* destination = NULL);
};
typedef CJsonParser *PJSonParser;

#endif
