6e237b
#pragma once
6e237b
6e237b
#ifndef TVARIANT_INCLUDED
6e237b
#define TVARIANT_INCLUDED
6e237b
6e237b
#include <tcommon.h></tcommon.h>
9cf1a4
#include <texception.h></texception.h>
6e237b
#include <tstringid.h></tstringid.h>
6e237b
9cf1a4
#include <iostream></iostream>
6e237b
#include <string></string>
6e237b
#include <vector></vector>
6e237b
#include <map></map>
6e237b
6e237b
#undef DVAPI
6e237b
#undef DVVAR
6e237b
#ifdef TVARIANT_EXPORTS
6e237b
#define DVAPI DV_EXPORT_API
6e237b
#define DVVAR DV_EXPORT_VAR
6e237b
#else
6e237b
#define DVAPI DV_IMPORT_API
6e237b
#define DVVAR DV_IMPORT_VAR
6e237b
#endif
6e237b
6e237b
//-------------------------------------------------------------------
6e237b
6e237b
class TVariant;
6e237b
typedef std::vector<tvariant> TVariantList;</tvariant>
6e237b
typedef std::map<tstringid, tvariant=""> TVariantMap;</tstringid,>
6e237b
6e237b
//-------------------------------------------------------------------
6e237b
9cf1a4
class TVariantSyntaxException final: public TException {
9cf1a4
public:
9cf1a4
  explicit TVariantSyntaxException(
9cf1a4
    int row = 0,
9cf1a4
    int col = 0,
9cf1a4
    const std::string &msg = std::string()
9cf1a4
  ):
9cf1a4
    TException(std::to_string(row) + ":" + std::to_string(col) + ": " + msg) { }
9cf1a4
};
9cf1a4
9cf1a4
//-------------------------------------------------------------------
9cf1a4
6e237b
class DVAPI TVariantPathEntry {
6e237b
private:
6e237b
  int m_index;
6e237b
  TStringId m_field;
6e237b
public:
6e237b
  inline explicit TVariantPathEntry(int index = -1):
6e237b
    m_index(index) { }
6e237b
  inline explicit TVariantPathEntry(const TStringId &field):
6e237b
    m_index(-1), m_field(field) { }
6e237b
  inline explicit TVariantPathEntry(const std::string &fieldName):
6e237b
    m_index(-1), m_field(fieldName) { }
6e237b
6e237b
  inline bool isIndex() const
6e237b
    { return m_index >= 0; }
6e237b
  inline bool isField() const
6e237b
    { return !isIndex(); }
6e237b
  inline int index() const
6e237b
    { return m_index; }
3bac66
  inline TStringId field() const
6e237b
    { return m_field; }
6e237b
6e237b
  inline bool operator== (const TVariantPathEntry &other) const
6e237b
    { return m_index == other.m_index && m_field == other.m_field; }
6e237b
  inline bool operator!= (const TVariantPathEntry &other) const
6e237b
    { return m_index != other.m_index || m_field != other.m_field; }
6e237b
  inline bool operator< (const TVariantPathEntry &other) const
6e237b
    { return m_index < other.m_index || m_field < other.m_field; }
6e237b
6e237b
  inline void set(int index)
6e237b
    { m_index = index; m_field.reset(); }
6e237b
  inline void set(const TStringId &field)
6e237b
    { m_index = 0; m_field = field; }
6e237b
  inline void set(const std::string &fieldName)
6e237b
    { m_index = 0; m_field.set(fieldName); }
6e237b
};
6e237b
6e237b
//-------------------------------------------------------------------
6e237b
6e237b
class DVAPI TVariantPath: public std::vector<tvariantpathentry> {</tvariantpathentry>
6e237b
public:
9cf8be
  inline TVariantPath& append(const TVariantPathEntry &x)
9cf8be
    { push_back(x); return *this; }
9cf8be
  inline TVariantPath& append(const TVariantPath &x)
9cf8be
    { insert(end(), x.begin(), x.end()); return *this; }
9cf8be
6e237b
  inline bool isSubPathOf(const TVariantPath &other) const
16421e
    { return compare(*this, 0, other, 0, (int)size()) == 0; }
6e237b
  inline bool isBasePathOf(const TVariantPath &other) const
6e237b
    { return other.isSubPathOf(*this); }
6e237b
  inline int compare(const TVariantPath &other) const
6e237b
    { return compare(*this, 0, other, 0, (int)std::max(size(), other.size())); }
6e237b
  inline bool operator==(const TVariantPath &other) const
6e237b
    { return compare(other) == 0; }
6e237b
  inline bool operator!=(const TVariantPath &other) const
6e237b
    { return compare(other) != 0; }
6e237b
  inline bool operator<(const TVariantPath &other) const
6e237b
    { return compare(other) < 0; }
6e237b
6e237b
  static int compare(
6e237b
    const TVariantPath &a, int beginA,
6e237b
    const TVariantPath &b, int beginB, int count );
6e237b
};
6e237b
6e237b
//-------------------------------------------------------------------
6e237b
6e237b
class DVAPI TVariantOwner {
6e237b
public:
6e237b
  virtual ~TVariantOwner() { }
ae9154
  virtual void onVariantChanged(const TVariant &value) { }
6e237b
};
6e237b
6e237b
//-------------------------------------------------------------------
6e237b
6e237b
class DVAPI TVariant {
6e237b
public:
6e237b
  enum Type {
6e237b
    None,
6e237b
    Bool,
6e237b
    Double,
6e237b
    String,
6e237b
    List,
6e237b
    Map
6e237b
  };
6e237b
6e237b
private:
6e237b
  Type         m_type;
6e237b
  bool         m_bool;
6e237b
  double       m_double;
6e237b
  std::string  m_string;
6e237b
  TVariantList m_list;
6e237b
  TVariantMap  m_map;
6e237b
6e237b
  TVariantOwner* m_owner;
6e237b
  TVariant *m_root;
6e237b
  TVariant *m_parent;
6e237b
  TStringId m_parentField;
6e237b
6e237b
  void setParentForChilds();
6e237b
  inline void setParent(TVariant &parent, const TStringId &parentField = TStringId()) {
6e237b
    m_root = parent.m_root;
6e237b
    m_parent = &parent;
6e237b
    m_parentField = parentField;
6e237b
    setParentForChilds();
6e237b
  }
6e237b
6e237b
public:
6e237b
  static const TVariant& blank();
6e237b
6e237b
  inline TVariant():
6e237b
    m_type(None),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { }
6e237b
  inline TVariant(const TVariant &other):
6e237b
    m_type(None),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { *this = other; }
6e237b
  inline explicit TVariant(TVariantOwner &owner, const TVariant &v = TVariant()):
6e237b
    m_type(None),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { *this = v; m_owner = &owner; }
6e237b
  inline explicit TVariant(Type t):
6e237b
    m_type(t),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { }
6e237b
  inline explicit TVariant(bool v):
6e237b
    m_type(Bool),
6e237b
    m_bool(v),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { }
6e237b
  inline explicit TVariant(double v):
6e237b
    m_type(Double),
6e237b
    m_bool(),
6e237b
    m_double(v),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { }
6e237b
  inline explicit TVariant(const std::string &v):
6e237b
    m_type(String),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_string(v),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { }
6e237b
  inline explicit TVariant(const TVariantList &v):
6e237b
    m_type(None),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { setList(v); }
6e237b
  inline explicit TVariant(const TVariantMap &v):
6e237b
    m_type(None),
6e237b
    m_bool(),
6e237b
    m_double(),
6e237b
    m_owner(),
6e237b
    m_root(this),
6e237b
    m_parent() { setMap(v); }
6e237b
6e237b
  inline void touch()
ae9154
    { if (m_root->m_owner) m_root->m_owner->onVariantChanged(*this); }
6e237b
6e237b
  inline TVariant& operator=(const TVariant &other) {
6e237b
    switch(other.m_type) {
6e237b
    case Bool   : setBool(other.m_bool); break;
6e237b
    case Double : setDouble(other.m_double); break;
6e237b
    case String : setString(other.m_string); break;
6e237b
    case List   : setList(other.m_list); break;
6e237b
    case Map    : setMap(other.m_map); break;
6e237b
    default     : reset(); break;
6e237b
    }
6e237b
    return *this;
6e237b
  }
6e237b
6e237b
  inline void clear() {
6e237b
    m_bool = bool();
6e237b
    m_double = double();
6e237b
    m_string.clear();
6e237b
    m_list.clear();
6e237b
    m_map.clear();
6e237b
    touch();
6e237b
  }
6e237b
  inline void setType(Type t)
6e237b
    { if (m_type != t) { m_type = t; clear(); } }
6e237b
  inline void reset()
6e237b
    { setType(None); }
6e237b
6e237b
  inline Type getType() const
6e237b
    { return m_type; }
6e237b
  inline bool isNone() const
6e237b
    { return m_type == None; }
6e237b
  inline bool getBool() const
6e237b
    { return m_bool; }
6e237b
  inline double getDouble() const
6e237b
    { return m_double; }
6e237b
  inline const std::string& getString() const
6e237b
    { return m_string; }
6e237b
  inline const TVariantList& getList() const
6e237b
    { return m_list; }
6e237b
  inline const TVariantMap& getMap() const
6e237b
    { return m_map; }
6e237b
6e237b
  inline void setNone()
6e237b
    { reset(); }
6e237b
  inline void setBool(bool v)
6e237b
    { setType(Bool); m_bool = v; touch(); }
6e237b
  inline void setDouble(double v)
6e237b
    { setType(Double); m_double = v; touch(); }
6e237b
  inline void setString(const std::string &v)
6e237b
    { setType(String); m_string = v; touch(); }
6e237b
  inline void setList(const TVariantList &v)
6e237b
    { setType(List); m_list = v; setParentForChilds(); touch(); }
6e237b
  inline void setMap(const TVariantMap &v)
6e237b
    { setType(Map); m_map = v; setParentForChilds(); touch(); }
6e237b
6e237b
  // list methods
6e237b
  void resize(int size);
6e237b
  void insert(int index, const TVariant &v);
6e237b
  void remove(int index);
6e237b
  TVariant& operator[] (int index);
6e237b
  inline int size() const
6e237b
    { return (int)(m_type == List ? m_list.size() : m_map.size()); }
6e237b
  inline void clearList()
6e237b
    { resize(0); }
6e237b
  inline void append(const TVariant &v)
6e237b
    { insert((int)m_list.size(), v); }
6e237b
  inline const TVariant& operator[] (int index) const {
6e237b
    assert(index >= 0);
6e237b
    return index < (int)m_list.size() ? m_list[index] : blank();
6e237b
  }
6e237b
6e237b
  // map methods
6e237b
  TVariant& operator[] (const TStringId &field);
6e237b
  bool remove(const TStringId &field);
6e237b
  inline bool contains(const TStringId &field) const
6e237b
    { return m_type == Map && m_map.count(field); }
6e237b
  inline const TVariant& operator[] (const TStringId &field) const {
6e237b
    TVariantMap::const_iterator i = m_map.find(field);
6e237b
    return i == m_map.end() ? blank() : i->second;
6e237b
  }
6e237b
  inline bool contains(const std::string &field) const
6e237b
    { return contains(TStringId::find(field)); }
6e237b
  inline const TVariant& operator[] (const std::string &field) const
6e237b
    { return (*this)[TStringId::find(field)]; }
6e237b
  inline TVariant& operator[] (const std::string &field)
9cf1a4
    { return (*this)[TStringId(field)]; }
6e237b
  inline void remove(const std::string &field)
6e237b
    { remove(TStringId::find(field)); }
6e237b
6e237b
  // path methods
6e237b
  const TVariant& byPath(const TVariantPath &path, int begin, int end) const;
6e237b
  TVariant& byPath(const TVariantPath &path, int begin, int end);
9cf8be
  inline const TVariant& operator[] (const TVariantPathEntry &entry) const {
6e237b
    return entry.isIndex()
6e237b
         ? (m_type == List ? (*this)[entry.index()] : blank())
6e237b
         : (m_type == Map  ? (*this)[entry.field()] : blank());
6e237b
  }
9cf8be
  inline TVariant& operator[] (const TVariantPathEntry &entry)
6e237b
    { return entry.isIndex() ? (*this)[entry.index()] : (*this)[entry.field()]; }
6e237b
  inline const TVariant& byPath(const TVariantPath &path, int begin = 0) const
6e237b
    { return byPath(path, begin, (int)path.size()); }
6e237b
  inline TVariant& byPath(const TVariantPath &path, int begin = 0)
6e237b
    { return byPath(path, begin, (int)path.size()); }
6e237b
  inline const TVariant& operator[] (const TVariantPath &path) const
6e237b
    { return byPath(path); }
6e237b
  inline TVariant& operator[] (const TVariantPath &path)
6e237b
    { return byPath(path); }
6e237b
6e237b
  // hierarchy methods
6e237b
  inline const TVariantOwner* owner() const
6e237b
    { return m_root->m_owner; }
6e237b
  inline TVariantOwner* owner()
6e237b
    { return m_root->m_owner; }
6e237b
  inline const TVariant& root() const
6e237b
    { return *m_root; }
6e237b
  inline TVariant& root()
6e237b
    { return *m_root; }
6e237b
  inline const TVariant* parent() const
6e237b
    { return m_parent; }
6e237b
  inline TVariant* parent()
6e237b
    { return m_parent; }
6e237b
  inline int parentIndex() const
6e237b
    { return m_parent || !m_parentField ? this - &m_parent->m_list.front() : 0; }
6e237b
  inline const TStringId& parentField() const
6e237b
    { return m_parentField; }
ae9154
  inline bool isRoot() const
ae9154
    { return this == m_root; }
6e237b
9cf8be
  int getParentPathSize(const TVariant &parent) const;
9cf8be
  bool getParentPath(TVariantPath &outPath, const TVariant &parent) const;
6e237b
  inline TVariantPathEntry parentPathEntry() const {
6e237b
    return !m_parent               ? TVariantPathEntry()
6e237b
         : m_parent->m_type == Map ? TVariantPathEntry(m_parentField)
6e237b
         : TVariantPathEntry( this - &m_parent->m_list.front() );
6e237b
  }
9cf8be
  inline int getParentPathSize() const
9cf8be
    { return getParentPathSize(*m_root); }
9cf8be
  inline bool getParentPath(TVariantPath &outPath) const
9cf8be
    { return getParentPath(outPath, *m_root); }
9cf8be
9cf8be
  inline int getChildPathSize(const TVariant &child) const
9cf8be
    { return child.getParentPathSize(*this); }
9cf8be
  inline bool getChildPath(TVariantPath &outPath, const TVariant &child) const
9cf8be
    { return child.getParentPath(outPath, *this); }
9cf8be
  bool getChildPathEntry(const TVariant &child, TVariantPathEntry &outEntry) const;
6e237b
6e237b
  bool isChildOf(const TVariant &other) const;
6e237b
  bool isChildOrEqual(const TVariant &other) const;
6e237b
  inline bool isParentOf(const TVariant &other) const
6e237b
    { return other.isChildOf(*this); }
6e237b
  inline bool isParentOrEqual(const TVariant &other) const
6e237b
    { return other.isChildOrEqual(*this); }
6e237b
  inline bool isChildOrParent(const TVariant &other) const
6e237b
    { return isChildOrEqual(other) || isParentOrEqual(other); }
6e237b
6e237b
  const TVariant* findCommonParent(const TVariant &other) const;
6e237b
249386
  // memory
249386
  size_t getMemSize() const;
249386
6e237b
  // serialization
9cf1a4
  void toStream(std::ostream &stream, bool pretty = false, int level = 0) const;
9cf1a4
  void fromStream(std::istream &stream, int *currentRow = 0, int *currentCol = 0);
9cf1a4
9cf1a4
  std::string toString(bool pretty = false, int level = 0) const;
9cf1a4
  void fromString(const std::string &str, int *currentRow = 0, int *currentCol = 0);
6e237b
};
6e237b
6e237b
#endif