/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This 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 2.1 of the License, or (at your option) any later version.
**
**  This file 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 library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2009-06-07
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef XMLPARSER_H
#define XMLPARSER_H

#include "XMLClass.h"
#include "Translations.h"

namespace QGpCoreTools {

class XMLParser
{
  TRANSLATIONS("XMLParser")
public:
  XMLParser(XMLStream * s, XMLContext * context=nullptr);
  ~XMLParser();

  void setLine(int l) {_line=l;}
  void setPointer(const QChar * ptr) {_ptr=ptr;}
  XMLClass::Error parse(XMLClass * object);
private:
  void openContext();
  void closeContext();
  void smallContext();
  QString currentContextTag();
  void restoreBinaryData();
  void restoreBinaryData200510();
  void skipSpecChar();
  void skipDoubleQuoteString();
  void skipSimpleQuoteString();
  void skip();
  void restoreSpecChar();
  void setTag();
  void setAttributes();
  void finish(XMLClass::Error err);
  static QChar specialCharacter(const StringSection& code, bool& ok);

  class Tag
  {
  public:
    Tag() : _member(XMLMember::Unknown) {}
    Tag(const StringSection& t) : _member(XMLMember::Unknown), _tag(t) {}
    Tag(const StringSection& t, const XMLMember& m) : _member(m), _tag(t) {}
    Tag(const Tag& t) : _member(t._member), _tag(t._tag) {}

    const XMLMember&  member() const {return _member;}
    const StringSection&  tag() const {return _tag;}
  private:
    XMLMember _member;
    StringSection _tag;
  };

  class Object
  {
  public:
    Object() : _context(nullptr), _object(nullptr) {}
    Object(XMLContext * context, XMLClass * object=nullptr) : _context(context), _object(object) {}
    Object(const Object& o) : _context(o._context), _object(o._object) {}

    void setObject(XMLClass * object) {_object=object;}
    XMLContext * context() const {return _context;}
    XMLClass * object() const {return _object;}
  private:
    XMLContext * _context;
    XMLClass * _object;
  };

  QStack<Tag> _tagStack;
  QStack<Object> _objectStack;

  Object _current;
  StringSection _tag;
  XMLMember _member;
  StringSection _content;
  XMLRestoreAttributes _attributes;

  XMLStream * _stream;
  const QChar * _ptr;
  int _line;
  XMLClass::Error _error;
  const QChar * _specChar;
  enum TagType {Unknown, OpenTagNoAttributes, OpenTagAttributes, SingleTagNoAttributes, SingleTagAttributes,
                Attributes, QuestionTagNoAttributes, QuestionTagAttributes, CloseTag};
  TagType _tagType;
  /* If the content must be altered (restoreSpecChar),
     it is redirected to this temp string to keep using a StringSection which requires a permanent string */
  QVector<QString *> _tmpStrings;
};

} // namespace QGpCoreTools

#endif // XMLPARSER_H
