6e237b
6e237b
6e237b
#include <tvariant.h></tvariant.h>
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
int
6e237b
TVariantPath::compare(
6e237b
  const TVariantPath &a, int beginA,
6e237b
  const TVariantPath &b, int beginB, int count )
6e237b
{
6e237b
  assert(beginA >= 0 && beginA <= (int)a.size());
6e237b
  assert(beginB >= 0 && beginB <= (int)b.size());
6e237b
  if (count == 0) return 0;
6e237b
  int countA = std::min(count, (int)a.size() - beginA);
6e237b
  int countB = std::min(count, (int)b.size() - beginB);
6e237b
  count = std::min(countA, countB);
6e237b
6e237b
  TVariantPath::const_iterator ia = a.begin() + beginA;
6e237b
  TVariantPath::const_iterator ib = b.begin() + beginB;
6e237b
  for(int i = 0; i < count; ++i, ++ia, ++ib)
6e237b
    if ((*ia) < (*ib)) return -1; else
6e237b
      if ((*ib) < (*ia)) return 1;
6e237b
  return countA < countB ? -1
6e237b
       : countB < countA ?  1 : 0;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
void
6e237b
TVariant::setParentForChilds() {
6e237b
  if (m_type == List) {
6e237b
    for(TVariantList::iterator i = m_list.begin(); i != m_list.end(); ++i)
6e237b
      i->setParent(*this);
6e237b
  } else
6e237b
  if (m_type == Map) {
6e237b
    for(TVariantMap::iterator i = m_map.begin(); i != m_map.end(); ++i)
6e237b
      i->second.setParent(*this, i->first);
6e237b
  }
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
const TVariant&
6e237b
TVariant::blank() {
6e237b
  static const TVariant blank;
6e237b
  return blank;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
void
6e237b
TVariant::resize(int size) {
6e237b
  setType(List);
6e237b
  int prevSize = (int)m_list.size();
6e237b
  if (prevSize == size) return;
6e237b
  m_list.resize(size);
6e237b
  if (prevSize < size)
6e237b
    for(TVariantList::iterator i = m_list.begin() + prevSize; i != m_list.end(); ++i)
6e237b
      i->setParent(*this);
6e237b
  touch();
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
void
6e237b
TVariant::insert(int index, const TVariant &v) {
6e237b
  resize(std::max((int)m_list.size(), index));
6e237b
  m_list.insert(m_list.begin() + index, v);
6e237b
  m_list[index].setParent(*this);
6e237b
  touch();
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
void
6e237b
TVariant::remove(int index) {
6e237b
  if (m_type == List && index >= 0 && index < (int)m_list.size())
6e237b
    { m_list.erase(m_list.begin() + index); touch(); }
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
TVariant&
6e237b
TVariant::operator[] (int index) {
6e237b
  setType(List);
6e237b
  assert(index >= 0);
6e237b
  int prevSize = (int)m_list.size();
6e237b
  if (index >= prevSize) {
6e237b
    m_list.resize(index + 1);
6e237b
    for(TVariantList::iterator i = m_list.begin() + prevSize; i != m_list.end(); ++i)
6e237b
      i->setParent(*this);
6e237b
    touch();
6e237b
  }
6e237b
  return m_list[index];
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
TVariant&
6e237b
TVariant::operator[] (const TStringId &field) {
6e237b
  setType(Map);
6e237b
  TVariant &result = m_map[field];
ae9154
  if (!result.m_parent) {
ae9154
    result.setParent(*this, field);
ae9154
    touch();
ae9154
  }
6e237b
  return result;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
bool
6e237b
TVariant::remove(const TStringId &field) {
6e237b
  if (m_type == Map && m_map.erase(field))
6e237b
    { touch(); return true; }
6e237b
  return false;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
const TVariant&
6e237b
TVariant::byPath(const TVariantPath &path, int begin, int end) const {
6e237b
  if ((int)path.size() <= begin || begin >= end) return *this;
6e237b
  if (isNone()) return blank();
9cf8be
  return (*this)[path[begin]].byPath(path, begin + 1, end);
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
TVariant&
6e237b
TVariant::byPath(const TVariantPath &path, int begin, int end) {
6e237b
  if ((int)path.size() <= begin || begin >= end) return *this;
9cf8be
  return (*this)[path[begin]].byPath(path, begin + 1, end);
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
int
9cf8be
TVariant::getParentPathSize(const TVariant &parent) const {
6e237b
  int ac = 0;
9cf8be
  for(const TVariant *a = this; a; a = a->parent(), ++ac)
9cf8be
    if (a == &parent) return ac;
9cf8be
  return -1;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
9cf8be
bool
9cf8be
TVariant::getParentPath(TVariantPath &outPath, const TVariant &parent) const {
9cf8be
  if (!m_parent)
9cf8be
    { outPath.clear(); return false; }
9cf8be
  if (m_parent == this)
9cf8be
    { outPath.clear(); return true; }
9cf8be
  if (m_parent->getParentPath(outPath))
9cf8be
    { outPath.push_back(parentPathEntry()); return true; }
9cf8be
  return false;
9cf8be
}
9cf8be
9cf8be
//---------------------------------------------------------
9cf8be
9cf8be
bool
9cf8be
TVariant::getChildPathEntry(const TVariant &child, TVariantPathEntry &outEntry) const {
9cf8be
  for(const TVariant *a = &child; a->parent(); a = a->parent())
9cf8be
    if (a->parent() == this)
9cf8be
      { outEntry = a->parentPathEntry(); return true; }
9cf8be
  outEntry = TVariantPathEntry();
9cf8be
  return false;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
bool
6e237b
TVariant::isChildOf(const TVariant &other) const {
6e237b
  for(const TVariant *a = this->m_parent; a; a = a->m_parent)
6e237b
    if (a == &other) return true;
6e237b
  return false;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
bool
6e237b
TVariant::isChildOrEqual(const TVariant &other) const {
6e237b
  for(const TVariant *a = this; a; a = a->m_parent)
6e237b
    if (a == &other) return true;
6e237b
  return false;
6e237b
}
6e237b
6e237b
//---------------------------------------------------------
6e237b
6e237b
const TVariant*
6e237b
TVariant::findCommonParent(const TVariant &other) const {
6e237b
  if (m_root != other.m_root) return NULL;
6e237b
  const TVariant *a = this, *b = &other;
6e237b
  int ac = 0, bc = 0;
6e237b
  while(a->m_parent) a = a->m_parent, ++ac;
6e237b
  while(b->m_parent) b = b->m_parent, ++bc;
6e237b
6e237b
  a = this, b = &other;
6e237b
  while(ac > bc) a = a->m_parent, --ac;
6e237b
  while(bc > ac) b = b->m_parent, --bc;
6e237b
6e237b
  while(true) {
6e237b
    if (a == b) return a;
6e237b
    if (ac == 0) break;
6e237b
    --ac, a = a->m_parent, b = b->m_parent;
6e237b
  }
6e237b
6e237b
  return NULL;
6e237b
}