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