// // Object.cpp // // Library: JSON // Package: JSON // Module: Object // // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // #include "Poco/JSON/Object.h" #include #include using Poco::Dynamic::Var; namespace Poco { namespace JSON { Object::Object(int options): _preserveInsOrder((options & Poco::JSON_PRESERVE_KEY_ORDER) != 0), _escapeUnicode((options & Poco::JSON_ESCAPE_UNICODE) != 0), _modified(false) { } Object::Object(const Object& other) : _values(other._values), _preserveInsOrder(other._preserveInsOrder), _escapeUnicode(other._escapeUnicode), _pStruct(!other._modified ? other._pStruct : 0), _modified(other._modified) { syncKeys(other._keys); } Object::Object(Object&& other) noexcept: _values(std::move(other._values)), _keys(std::move(other._keys)), _preserveInsOrder(other._preserveInsOrder), _escapeUnicode(other._escapeUnicode), _pStruct(std::move(other._pStruct)), _pOrdStruct(std::move(other._pOrdStruct)), _modified(other._modified) { } Object::~Object() { } Object &Object::operator = (const Object &other) { if (&other != this) { _values = other._values; _keys = other._keys; _preserveInsOrder = other._preserveInsOrder; _escapeUnicode = other._escapeUnicode; _pStruct = !other._modified ? other._pStruct : 0; _modified = other._modified; } return *this; } Object& Object::operator = (Object&& other) noexcept { _values = std::move(other._values); _keys = std::move(other._keys); _preserveInsOrder = other._preserveInsOrder; _escapeUnicode = other._escapeUnicode; _pStruct = std::move(other._pStruct); _pOrdStruct = std::move(other._pOrdStruct); _modified = other._modified; return *this; } void Object::syncKeys(const KeyList& keys) { if(_preserveInsOrder) { // update iterators in _keys to point to copied _values for(KeyList::const_iterator it = keys.begin(); it != keys.end(); ++it) { ValueMap::const_iterator itv = _values.find((*it)->first); poco_assert (itv != _values.end()); _keys.push_back(itv); } } } Var Object::get(const std::string& key) const { ValueMap::const_iterator it = _values.find(key); if (it != _values.end()) { return it->second; } return Var(); } Array::Ptr Object::getArray(const std::string& key) const { ValueMap::const_iterator it = _values.find(key); if ((it != _values.end()) && (it->second.type() == typeid(Array::Ptr))) { return it->second.extract(); } return 0; } Object::Ptr Object::getObject(const std::string& key) const { ValueMap::const_iterator it = _values.find(key); if ((it != _values.end()) && (it->second.type() == typeid(Object::Ptr))) { return it->second.extract(); } return 0; } void Object::getNames(NameList& names) const { names.clear(); if (_preserveInsOrder) { for(KeyList::const_iterator it = _keys.begin(); it != _keys.end(); ++it) { names.push_back((*it)->first); } } else { for(ValueMap::const_iterator it = _values.begin(); it != _values.end(); ++it) { names.push_back(it->first); } } } Object::NameList Object::getNames() const { NameList names; getNames(names); return names; } void Object::stringify(std::ostream& out, unsigned int indent, int step) const { if (step < 0) step = indent; if (!_preserveInsOrder) doStringify(_values, out, indent, step); else doStringify(_keys, out, indent, step); } const std::string& Object::getKey(KeyList::const_iterator& iter) const { ValueMap::const_iterator it = _values.begin(); ValueMap::const_iterator end = _values.end(); for (; it != end; ++it) { if (it == *iter) return it->first; } throw NotFoundException((*iter)->first); } Object& Object::set(const std::string& key, const Dynamic::Var& value) { std::pair ret = _values.insert(ValueMap::value_type(key, value)); if (!ret.second) ret.first->second = value; if (_preserveInsOrder) { KeyList::iterator it = _keys.begin(); KeyList::iterator end = _keys.end(); for (; it != end; ++it) { if (key == (*it)->first) return *this; } _keys.push_back(ret.first); } _modified = true; return *this; } Poco::DynamicStruct Object::makeStruct(const Object::Ptr& obj) { return makeStructImpl(obj); } Poco::OrderedDynamicStruct Object::makeOrderedStruct(const Object::Ptr& obj) { return makeStructImpl(obj); } /* void Object::resetOrdDynStruct() const { if (!_pOrdStruct) _pOrdStruct = new Poco::OrderedDynamicStruct; else _pOrdStruct->clear(); } */ /* void Object::resetDynStruct() const { if (!_pStruct) _pStruct = new Poco::DynamicStruct; else _pStruct->clear(); }*/ Object::operator const Poco::DynamicStruct& () const { if (!_values.size()) { resetDynStruct(_pStruct); } else if (_modified) { ValueMap::const_iterator it = _values.begin(); ValueMap::const_iterator end = _values.end(); resetDynStruct(_pStruct); for (; it != end; ++it) { if (isObject(it)) { _pStruct->insert(it->first, makeStruct(getObject(it->first))); } else if (isArray(it)) { _pStruct->insert(it->first, Poco::JSON::Array::makeArray(getArray(it->first))); } else { _pStruct->insert(it->first, it->second); } } } return *_pStruct; } Object::operator const Poco::OrderedDynamicStruct& () const { if (!_values.size()) { resetDynStruct(_pOrdStruct); } else if (_modified) { if (_preserveInsOrder) { KeyList::const_iterator it = _keys.begin(); KeyList::const_iterator end = _keys.end(); resetDynStruct(_pOrdStruct); for (; it != end; ++it) { if (isObject((*it)->first)) { _pOrdStruct->insert((*it)->first, makeOrderedStruct(getObject((*it)->first))); } else if (isArray((*it)->first)) { _pOrdStruct->insert((*it)->first, Poco::JSON::Array::makeArray(getArray((*it)->first))); } else { _pOrdStruct->insert((*it)->first, (*it)->second); } } } else { ValueMap::const_iterator it = _values.begin(); ValueMap::const_iterator end = _values.end(); resetDynStruct(_pOrdStruct); for (; it != end; ++it) { if (isObject(it)) { _pOrdStruct->insert(it->first, makeOrderedStruct(getObject(it->first))); } else if (isArray(it)) { _pOrdStruct->insert(it->first, Poco::JSON::Array::makeArray(getArray(it->first))); } else { _pOrdStruct->insert(it->first, it->second); } } } } return *_pOrdStruct; } void Object::clear() { _values.clear(); _keys.clear(); _pStruct = 0; _modified = true; } } } // namespace Poco::JSON