| |
| |
| #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; |
| } |
| |