mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +01:00
* Preserve entries order in DynamicStruct #2410 * disable C++11 default * ifdef C++11 code
This commit is contained in:
parent
6107b43a7b
commit
231ef2762d
@ -22,6 +22,8 @@
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Dynamic/VarHolder.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/OrderedMap.h"
|
||||
#include "Poco/OrderedSet.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
@ -30,19 +32,19 @@ namespace Poco {
|
||||
namespace Dynamic {
|
||||
|
||||
|
||||
template <typename K>
|
||||
template <typename K, typename M = std::map<K, Var>, typename S = std::set<K> >
|
||||
class Struct
|
||||
/// Struct allows to define a named collection of Var objects.
|
||||
{
|
||||
public:
|
||||
typedef typename std::map<K, Var> Data;
|
||||
typedef typename std::set<K> NameSet;
|
||||
typedef M Data;
|
||||
typedef S NameSet;
|
||||
typedef typename Data::iterator Iterator;
|
||||
typedef typename Data::const_iterator ConstIterator;
|
||||
typedef typename Struct<K>::Data::value_type ValueType;
|
||||
typedef typename Struct<K>::Data::size_type SizeType;
|
||||
typedef typename std::pair<typename Struct<K>::Iterator, bool> InsRetVal;
|
||||
typedef typename Poco::SharedPtr<Struct<K> > Ptr;
|
||||
typedef typename std::pair<typename Struct<K, M, S>::Iterator, bool> InsRetVal;
|
||||
typedef typename Poco::SharedPtr<Struct<K, M, S> > Ptr;
|
||||
|
||||
Struct(): _data()
|
||||
/// Creates an empty Struct
|
||||
@ -57,13 +59,19 @@ public:
|
||||
template <typename T>
|
||||
Struct(const std::map<K, T>& val)
|
||||
{
|
||||
typedef typename std::map<K, T>::const_iterator MapConstIterator;
|
||||
|
||||
MapConstIterator it = val.begin();
|
||||
MapConstIterator end = val.end();
|
||||
for (; it != end; ++it) _data.insert(ValueType(it->first, Var(it->second)));
|
||||
assignMap(val);
|
||||
}
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
template <typename T>
|
||||
Struct(const OrderedMap<K, T>& val)
|
||||
{
|
||||
assignMap(val);
|
||||
}
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
virtual ~Struct()
|
||||
/// Destroys the Struct.
|
||||
{
|
||||
@ -199,15 +207,30 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void assignMap(const T& map)
|
||||
{
|
||||
typedef typename T::const_iterator MapConstIterator;
|
||||
|
||||
MapConstIterator it = map.begin();
|
||||
MapConstIterator end = map.end();
|
||||
for (; it != end; ++it) _data.insert(ValueType(it->first, Var(it->second)));
|
||||
}
|
||||
|
||||
Data _data;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
class VarHolderImpl<Struct<std::string> >: public VarHolder
|
||||
class VarHolderImpl<Struct<std::string, std::map<std::string, Var>, std::set<std::string> > >: public VarHolder
|
||||
{
|
||||
public:
|
||||
VarHolderImpl(const Struct<std::string>& val): _val(val)
|
||||
typedef std::string KeyType;
|
||||
typedef std::map<KeyType, Var> MapType;
|
||||
typedef std::set<KeyType> SetType;
|
||||
typedef Struct<KeyType, MapType, SetType> ValueType;
|
||||
|
||||
VarHolderImpl(const ValueType& val): _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
@ -217,7 +240,7 @@ public:
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(Struct<std::string>);
|
||||
return typeid(ValueType);
|
||||
}
|
||||
|
||||
void convert(Int8&) const
|
||||
@ -283,8 +306,8 @@ public:
|
||||
void convert(std::string& val) const
|
||||
{
|
||||
val.append("{ ");
|
||||
Struct<std::string>::ConstIterator it = _val.begin();
|
||||
Struct<std::string>::ConstIterator itEnd = _val.end();
|
||||
ValueType::ConstIterator it = _val.begin();
|
||||
ValueType::ConstIterator itEnd = _val.end();
|
||||
if (!_val.empty())
|
||||
{
|
||||
Var key(it->first);
|
||||
@ -324,7 +347,7 @@ public:
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
}
|
||||
|
||||
const Struct<std::string>& value() const
|
||||
const ValueType& value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
@ -339,6 +362,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isOrdered() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return false;
|
||||
@ -364,26 +392,31 @@ public:
|
||||
return _val.size();
|
||||
}
|
||||
|
||||
Var& operator [] (const std::string& name)
|
||||
Var& operator [] (const KeyType& name)
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
const Var& operator [] (const std::string& name) const
|
||||
const Var& operator [] (const KeyType& name) const
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
private:
|
||||
Struct<std::string> _val;
|
||||
ValueType _val;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
class VarHolderImpl<Struct<int> >: public VarHolder
|
||||
class VarHolderImpl<Struct<int, std::map<int, Var>, std::set<int> > > : public VarHolder
|
||||
{
|
||||
public:
|
||||
VarHolderImpl(const Struct<int>& val): _val(val)
|
||||
typedef int KeyType;
|
||||
typedef std::map<KeyType, Var> MapType;
|
||||
typedef std::set<KeyType> SetType;
|
||||
typedef Struct<KeyType, MapType, SetType> ValueType;
|
||||
|
||||
VarHolderImpl(const ValueType& val) : _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
@ -393,7 +426,7 @@ public:
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(Struct<int>);
|
||||
return typeid(ValueType);
|
||||
}
|
||||
|
||||
void convert(Int8&) const
|
||||
@ -459,8 +492,8 @@ public:
|
||||
void convert(std::string& val) const
|
||||
{
|
||||
val.append("{ ");
|
||||
Struct<int>::ConstIterator it = _val.begin();
|
||||
Struct<int>::ConstIterator itEnd = _val.end();
|
||||
ValueType::ConstIterator it = _val.begin();
|
||||
ValueType::ConstIterator itEnd = _val.end();
|
||||
if (!_val.empty())
|
||||
{
|
||||
Var key(it->first);
|
||||
@ -500,7 +533,7 @@ public:
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
}
|
||||
|
||||
const Struct<int>& value() const
|
||||
const ValueType& value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
@ -515,6 +548,200 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isOrdered() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSigned() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNumeric() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return _val.size();
|
||||
}
|
||||
|
||||
Var& operator [] (const KeyType& name)
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
const Var& operator [] (const KeyType& name) const
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
private:
|
||||
ValueType _val;
|
||||
};
|
||||
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
|
||||
template <>
|
||||
class VarHolderImpl<Struct<std::string, Poco::OrderedMap<std::string, Var>, Poco::OrderedSet<std::string> > > : public VarHolder
|
||||
{
|
||||
public:
|
||||
typedef std::string KeyType;
|
||||
typedef Poco::OrderedMap<KeyType, Var> MapType;
|
||||
typedef Poco::OrderedSet<KeyType> SetType;
|
||||
typedef Struct<KeyType, MapType, SetType> ValueType;
|
||||
|
||||
VarHolderImpl(const ValueType& val) : _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
~VarHolderImpl()
|
||||
{
|
||||
}
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(ValueType);
|
||||
}
|
||||
|
||||
void convert(Int8&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int8");
|
||||
}
|
||||
|
||||
void convert(Int16&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int16");
|
||||
}
|
||||
|
||||
void convert(Int32&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int32");
|
||||
}
|
||||
|
||||
void convert(Int64&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int64");
|
||||
}
|
||||
|
||||
void convert(UInt8&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt8");
|
||||
}
|
||||
|
||||
void convert(UInt16&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt16");
|
||||
}
|
||||
|
||||
void convert(UInt32&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt32");
|
||||
}
|
||||
|
||||
void convert(UInt64&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt64");
|
||||
}
|
||||
|
||||
void convert(bool&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to bool");
|
||||
}
|
||||
|
||||
void convert(float&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to float");
|
||||
}
|
||||
|
||||
void convert(double&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to double");
|
||||
}
|
||||
|
||||
void convert(char&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to char");
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
{
|
||||
val.append("{ ");
|
||||
ValueType::ConstIterator it = _val.begin();
|
||||
ValueType::ConstIterator itEnd = _val.end();
|
||||
if (!_val.empty())
|
||||
{
|
||||
Var key(it->first);
|
||||
Impl::appendJSONKey(val, key);
|
||||
val.append(" : ");
|
||||
Impl::appendJSONValue(val, it->second);
|
||||
++it;
|
||||
}
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
val.append(", ");
|
||||
Var key(it->first);
|
||||
Impl::appendJSONKey(val, key);
|
||||
val.append(" : ");
|
||||
Impl::appendJSONValue(val, it->second);
|
||||
}
|
||||
val.append(" }");
|
||||
}
|
||||
|
||||
void convert(Poco::DateTime&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::DateTime");
|
||||
}
|
||||
|
||||
void convert(Poco::LocalDateTime&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::LocalDateTime");
|
||||
}
|
||||
|
||||
void convert(Poco::Timestamp&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::Timestamp");
|
||||
}
|
||||
|
||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||
{
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
}
|
||||
|
||||
const ValueType& value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isStruct() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isOrdered() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return false;
|
||||
@ -540,26 +767,218 @@ public:
|
||||
return _val.size();
|
||||
}
|
||||
|
||||
Var& operator [] (int name)
|
||||
Var& operator [] (const KeyType& name)
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
const Var& operator [] (int name) const
|
||||
const Var& operator [] (const KeyType& name) const
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
private:
|
||||
Struct<int> _val;
|
||||
ValueType _val;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
class VarHolderImpl<Struct<int, Poco::OrderedMap<int, Var>, Poco::OrderedSet<int> > > : public VarHolder
|
||||
{
|
||||
public:
|
||||
typedef int KeyType;
|
||||
typedef Poco::OrderedMap<KeyType, Var> MapType;
|
||||
typedef Poco::OrderedSet<KeyType> SetType;
|
||||
typedef Struct<KeyType, MapType, SetType> ValueType;
|
||||
|
||||
VarHolderImpl(const ValueType& val) : _val(val)
|
||||
{
|
||||
}
|
||||
|
||||
~VarHolderImpl()
|
||||
{
|
||||
}
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return typeid(ValueType);
|
||||
}
|
||||
|
||||
void convert(Int8&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int8");
|
||||
}
|
||||
|
||||
void convert(Int16&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int16");
|
||||
}
|
||||
|
||||
void convert(Int32&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int32");
|
||||
}
|
||||
|
||||
void convert(Int64&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to Int64");
|
||||
}
|
||||
|
||||
void convert(UInt8&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt8");
|
||||
}
|
||||
|
||||
void convert(UInt16&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt16");
|
||||
}
|
||||
|
||||
void convert(UInt32&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt32");
|
||||
}
|
||||
|
||||
void convert(UInt64&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to UInt64");
|
||||
}
|
||||
|
||||
void convert(bool&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to bool");
|
||||
}
|
||||
|
||||
void convert(float&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to float");
|
||||
}
|
||||
|
||||
void convert(double&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to double");
|
||||
}
|
||||
|
||||
void convert(char&) const
|
||||
{
|
||||
throw BadCastException("Cannot cast Struct type to char");
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
{
|
||||
val.append("{ ");
|
||||
ValueType::ConstIterator it = _val.begin();
|
||||
ValueType::ConstIterator itEnd = _val.end();
|
||||
if (!_val.empty())
|
||||
{
|
||||
Var key(it->first);
|
||||
Impl::appendJSONKey(val, key);
|
||||
val.append(" : ");
|
||||
Impl::appendJSONValue(val, it->second);
|
||||
++it;
|
||||
}
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
val.append(", ");
|
||||
Var key(it->first);
|
||||
Impl::appendJSONKey(val, key);
|
||||
val.append(" : ");
|
||||
Impl::appendJSONValue(val, it->second);
|
||||
}
|
||||
val.append(" }");
|
||||
}
|
||||
|
||||
void convert(Poco::DateTime&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::DateTime");
|
||||
}
|
||||
|
||||
void convert(Poco::LocalDateTime&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::LocalDateTime");
|
||||
}
|
||||
|
||||
void convert(Poco::Timestamp&) const
|
||||
{
|
||||
throw BadCastException("Struct -> Poco::Timestamp");
|
||||
}
|
||||
|
||||
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
|
||||
{
|
||||
return cloneHolder(pVarHolder, _val);
|
||||
}
|
||||
|
||||
const ValueType& value() const
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isStruct() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isOrdered() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSigned() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNumeric() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return _val.size();
|
||||
}
|
||||
|
||||
Var& operator [] (const KeyType& name)
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
const Var& operator [] (const KeyType& name) const
|
||||
{
|
||||
return _val[name];
|
||||
}
|
||||
|
||||
private:
|
||||
ValueType _val;
|
||||
};
|
||||
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
|
||||
} // namespace Dynamic
|
||||
|
||||
|
||||
typedef Dynamic::Struct<std::string> DynamicStruct;
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
typedef Dynamic::Struct<std::string, Poco::OrderedMap<std::string, Dynamic::Var>, Poco::OrderedSet<std::string> > OrderedDynamicStruct;
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
@ -21,16 +21,20 @@
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/OrderedMap.h"
|
||||
#include "Poco/OrderedSet.h"
|
||||
#include "Poco/Dynamic/VarHolder.h"
|
||||
#include "Poco/Dynamic/VarIterator.h"
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Dynamic {
|
||||
|
||||
|
||||
template <typename T>
|
||||
template <typename K, typename M, typename S>
|
||||
class Struct;
|
||||
|
||||
|
||||
@ -449,6 +453,10 @@ public:
|
||||
bool isStruct() const;
|
||||
/// Returns true if Var represents a struct.
|
||||
|
||||
bool isOrdered() const;
|
||||
/// Returns true if Var represents an ordered struct,
|
||||
/// false if struct is sorted.
|
||||
|
||||
char& at(std::size_t n);
|
||||
/// Returns character at position n. This function only works with
|
||||
/// Var containing a std::string.
|
||||
@ -595,7 +603,11 @@ private:
|
||||
throw E(errorMessage);
|
||||
}
|
||||
|
||||
Var& structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const;
|
||||
template <typename T, typename N>
|
||||
Var& structIndexOperator(T* pStr, N n) const
|
||||
{
|
||||
return pStr->operator[](n);
|
||||
}
|
||||
|
||||
#ifdef POCO_NO_SOO
|
||||
|
||||
@ -822,6 +834,13 @@ inline bool Var::isStruct() const
|
||||
}
|
||||
|
||||
|
||||
inline bool Var::isOrdered() const
|
||||
{
|
||||
VarHolder* pHolder = content();
|
||||
return pHolder ? pHolder->isOrdered() : false;
|
||||
}
|
||||
|
||||
|
||||
inline bool Var::isInteger() const
|
||||
{
|
||||
VarHolder* pHolder = content();
|
||||
|
@ -241,6 +241,10 @@ public:
|
||||
/// Returns false. Must be properly overriden in a type
|
||||
/// specialization in order to support the diagnostic.
|
||||
|
||||
virtual bool isOrdered() const;
|
||||
/// Returns false. Must be properly overriden in a type
|
||||
/// specialization in order to support the diagnostic.
|
||||
|
||||
virtual bool isInteger() const;
|
||||
/// Returns false. Must be properly overriden in a type
|
||||
/// specialization in order to support the diagnostic.
|
||||
@ -612,6 +616,13 @@ inline bool VarHolder::isStruct() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool VarHolder::isOrdered() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool VarHolder::isInteger() const
|
||||
{
|
||||
return false;
|
||||
|
@ -113,6 +113,8 @@ class SharedPtr
|
||||
/// is required.
|
||||
{
|
||||
public:
|
||||
typedef C Type;
|
||||
|
||||
SharedPtr(): _pCounter(new RC), _ptr(0)
|
||||
{
|
||||
}
|
||||
|
@ -362,8 +362,16 @@ Var& Var::getAt(std::size_t n)
|
||||
return holderImpl<std::deque<Var>,
|
||||
InvalidAccessException>("Not a deque.")->operator[](n);
|
||||
else if (isStruct())
|
||||
return structIndexOperator(holderImpl<Struct<int>,
|
||||
InvalidAccessException>("Not a struct."), static_cast<int>(n));
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
if (isOrdered())
|
||||
return structIndexOperator(holderImpl<Struct<int, OrderedMap<int, Var>, OrderedSet<int> >,
|
||||
InvalidAccessException>("Not a struct."), static_cast<int>(n));
|
||||
else
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
return structIndexOperator(holderImpl<Struct<int, std::map<int, Var>, std::set<int> >,
|
||||
InvalidAccessException>("Not a struct."), static_cast<int>(n));
|
||||
}
|
||||
else if (!isString() && !isEmpty() && (n == 0))
|
||||
return *this;
|
||||
|
||||
@ -385,8 +393,17 @@ char& Var::at(std::size_t n)
|
||||
|
||||
Var& Var::getAt(const std::string& name)
|
||||
{
|
||||
return holderImpl<DynamicStruct,
|
||||
InvalidAccessException>("Not a struct.")->operator[](name);
|
||||
if (isStruct())
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
if (isOrdered())
|
||||
return structIndexOperator(holderImpl<OrderedDynamicStruct, InvalidAccessException>("Not a struct."), name);
|
||||
else
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
return structIndexOperator(holderImpl<DynamicStruct, InvalidAccessException>("Not a struct."), name);
|
||||
}
|
||||
|
||||
throw InvalidAccessException("Not a struct.");
|
||||
}
|
||||
|
||||
|
||||
@ -626,11 +643,11 @@ std::string Var::toString(const Var& any)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Var& Var::structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const
|
||||
{
|
||||
return pStr->operator[](n);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
} } // namespace Poco::Dynamic
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "Poco/Dynamic/VarIterator.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Dynamic/Struct.h"
|
||||
//#include "Poco/Dynamic/Struct.h"
|
||||
#undef min
|
||||
#undef max
|
||||
#include <limits>
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <utility>
|
||||
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1400
|
||||
#pragma warning(disable:4800)//forcing value to bool 'true' or 'false'
|
||||
#endif
|
||||
@ -2256,6 +2255,34 @@ void VarTest::testDynamicStructBasics()
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testOrderedDynamicStructBasics()
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
OrderedDynamicStruct aStruct;
|
||||
assertTrue(aStruct.empty());
|
||||
assertTrue(aStruct.size() == 0);
|
||||
assertTrue(aStruct.members().empty());
|
||||
|
||||
aStruct.insert("First Name", "Little");
|
||||
assertTrue(!aStruct.empty());
|
||||
assertTrue(aStruct.size() == 1);
|
||||
assertTrue(*(aStruct.members().begin()) == "First Name");
|
||||
assertTrue(aStruct["First Name"] == "Little");
|
||||
aStruct.insert("Last Name", "POCO");
|
||||
assertTrue(aStruct.members().size() == 2);
|
||||
aStruct.erase("First Name");
|
||||
assertTrue(aStruct.size() == 1);
|
||||
assertTrue(*(aStruct.members().begin()) == "Last Name");
|
||||
aStruct.insert("Age", 1);
|
||||
assertTrue(aStruct["Age"] == 1);
|
||||
assertTrue(aStruct.members().size() == 2);
|
||||
assertTrue(*(aStruct.members().begin()) == "Last Name");
|
||||
aStruct.clear();
|
||||
assertTrue(aStruct.size() == 0);
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testDynamicStructString()
|
||||
{
|
||||
DynamicStruct aStruct;
|
||||
@ -2290,6 +2317,45 @@ void VarTest::testDynamicStructString()
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testOrderedDynamicStructString()
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
OrderedDynamicStruct aStruct;
|
||||
aStruct["First Name"] = "Junior";
|
||||
aStruct["Last Name"] = "POCO";
|
||||
Var a1(aStruct);
|
||||
assertTrue(a1["First Name"] == "Junior");
|
||||
assertTrue(a1["Last Name"] == "POCO");
|
||||
a1["First Name"] = "Senior";
|
||||
assertTrue(a1["First Name"] == "Senior");
|
||||
testGetIdxMustThrow(a1, 0);
|
||||
|
||||
typedef Struct<std::string, OrderedMap<std::string, Var>, OrderedSet<std::string> > OrderedStruct;
|
||||
OrderedStruct s1;
|
||||
s1["1"] = 1;
|
||||
s1["2"] = 2;
|
||||
s1["3"] = 3;
|
||||
|
||||
OrderedStruct s2(s1);
|
||||
assertTrue(s2["1"] == 1);
|
||||
assertTrue(s2["2"] == 2);
|
||||
assertTrue(s2["3"] == 3);
|
||||
|
||||
OrderedMap<std::string, int> m1;
|
||||
m1["2"] = 2;
|
||||
m1["1"] = 1;
|
||||
m1["3"] = 3;
|
||||
assertTrue (m1.begin()->first == "2");
|
||||
assertTrue(m1.begin()->second == 2);
|
||||
|
||||
OrderedStruct m2(m1);
|
||||
assertTrue(m2["1"] == 1);
|
||||
assertTrue(m2["2"] == 2);
|
||||
assertTrue(m2["3"] == 3);
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testDynamicStructInt()
|
||||
{
|
||||
Dynamic::Struct<int> aStruct;
|
||||
@ -2325,6 +2391,47 @@ void VarTest::testDynamicStructInt()
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testOrderedDynamicStructInt()
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
typedef Struct<int, OrderedMap<int, Var>, OrderedSet<int> > OrderedStruct;
|
||||
OrderedStruct aStruct;
|
||||
aStruct[0] = "POCO";
|
||||
aStruct[1] = "Junior";
|
||||
aStruct[2] = 100;
|
||||
aStruct[3] = 10;
|
||||
|
||||
Var a1(aStruct);
|
||||
assertTrue(a1[0] == "POCO");
|
||||
assertTrue(a1[1] == "Junior");
|
||||
assertTrue(a1[2] == 100);
|
||||
assertTrue(a1[3] == 10);
|
||||
a1[0] = "Senior";
|
||||
assertTrue(a1[0] == "Senior");
|
||||
|
||||
OrderedStruct s1;
|
||||
s1[1] = "1";
|
||||
s1[2] = "2";
|
||||
s1[3] = "3";
|
||||
|
||||
OrderedStruct s2(s1);
|
||||
assertTrue(s2[1] == "1");
|
||||
assertTrue(s2[2] == "2");
|
||||
assertTrue(s2[3] == "3");
|
||||
|
||||
OrderedMap<int, std::string> m1;
|
||||
m1[1] = "2";
|
||||
m1[2] = "1";
|
||||
m1[3] = "3";
|
||||
|
||||
OrderedStruct m2(m1);
|
||||
assertTrue(m2[1] == "2");
|
||||
assertTrue(m2[2] == "1");
|
||||
assertTrue(m2[3] == "3");
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testDynamicPair()
|
||||
{
|
||||
Pair<int> aPair;
|
||||
@ -2414,6 +2521,22 @@ void VarTest::testStructToString()
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testOrderedStructToString()
|
||||
{
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
OrderedDynamicStruct aStruct;
|
||||
aStruct["First Name"] = "Junior";
|
||||
aStruct["Last Name"] = "POCO";
|
||||
aStruct["Age"] = 1;
|
||||
Var a1(aStruct);
|
||||
std::string res = a1.convert<std::string>();
|
||||
std::string expected = "{ \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\", \"Age\" : 1 }";
|
||||
assertTrue(res == expected);
|
||||
assertTrue(aStruct.toString() == res);
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
}
|
||||
|
||||
|
||||
void VarTest::testStructToStringEscape()
|
||||
{
|
||||
DynamicStruct aStruct;
|
||||
@ -2959,11 +3082,15 @@ CppUnit::Test* VarTest::suite()
|
||||
CppUnit_addTest(pSuite, VarTest, testArrayIdxOperator);
|
||||
CppUnit_addTest(pSuite, VarTest, testDynamicPair);
|
||||
CppUnit_addTest(pSuite, VarTest, testDynamicStructBasics);
|
||||
CppUnit_addTest(pSuite, VarTest, testOrderedDynamicStructBasics);
|
||||
CppUnit_addTest(pSuite, VarTest, testDynamicStructString);
|
||||
CppUnit_addTest(pSuite, VarTest, testOrderedDynamicStructString);
|
||||
CppUnit_addTest(pSuite, VarTest, testDynamicStructInt);
|
||||
CppUnit_addTest(pSuite, VarTest, testOrderedDynamicStructInt);
|
||||
CppUnit_addTest(pSuite, VarTest, testArrayToString);
|
||||
CppUnit_addTest(pSuite, VarTest, testArrayToStringEscape);
|
||||
CppUnit_addTest(pSuite, VarTest, testStructToString);
|
||||
CppUnit_addTest(pSuite, VarTest, testOrderedStructToString);
|
||||
CppUnit_addTest(pSuite, VarTest, testStructToStringEscape);
|
||||
CppUnit_addTest(pSuite, VarTest, testArrayOfStructsToString);
|
||||
CppUnit_addTest(pSuite, VarTest, testStructWithArraysToString);
|
||||
|
@ -55,11 +55,15 @@ public:
|
||||
void testArrayIdxOperator();
|
||||
void testDynamicPair();
|
||||
void testDynamicStructBasics();
|
||||
void testOrderedDynamicStructBasics();
|
||||
void testDynamicStructString();
|
||||
void testOrderedDynamicStructString();
|
||||
void testDynamicStructInt();
|
||||
void testOrderedDynamicStructInt();
|
||||
void testArrayToString();
|
||||
void testArrayToStringEscape();
|
||||
void testStructToString();
|
||||
void testOrderedStructToString();
|
||||
void testStructToStringEscape();
|
||||
void testArrayOfStructsToString();
|
||||
void testStructWithArraysToString();
|
||||
|
@ -224,6 +224,16 @@ public:
|
||||
static Poco::DynamicStruct makeStruct(const Object::Ptr& obj);
|
||||
/// Utility function for creation of struct.
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
static Poco::OrderedDynamicStruct makeOrderedStruct(const Object::Ptr& obj);
|
||||
/// Utility function for creation of ordered struct.
|
||||
|
||||
operator const Poco::OrderedDynamicStruct& () const;
|
||||
/// Cast operator to Poco::OrderedDynamiStruct.
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
operator const Poco::DynamicStruct& () const;
|
||||
/// Cast operator to Poco::DynamiStruct.
|
||||
|
||||
@ -235,10 +245,21 @@ public:
|
||||
private:
|
||||
typedef std::deque<ValueMap::const_iterator> KeyList;
|
||||
typedef Poco::DynamicStruct::Ptr StructPtr;
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
typedef Poco::OrderedDynamicStruct::Ptr OrdStructPtr;
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
void resetDynStruct() const;
|
||||
void syncKeys(const KeyList& keys);
|
||||
|
||||
template <typename T>
|
||||
void resetDynStruct(T& pStruct) const
|
||||
{
|
||||
if (!pStruct)
|
||||
pStruct = new typename T::Type;
|
||||
else
|
||||
pStruct->clear();
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
void doStringify(const C& container, std::ostream& out, unsigned int indent, unsigned int step) const
|
||||
{
|
||||
@ -272,6 +293,59 @@ private:
|
||||
out << '}';
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static S makeStructImpl(const Object::Ptr& obj)
|
||||
{
|
||||
S ds;
|
||||
|
||||
if (obj->_preserveInsOrder)
|
||||
{
|
||||
KeyList::const_iterator it = obj->_keys.begin();
|
||||
KeyList::const_iterator end = obj->_keys.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (obj->isObject((*it)->first))
|
||||
{
|
||||
Object::Ptr pObj = obj->getObject((*it)->first);
|
||||
S str = makeStructImpl<S>(pObj);
|
||||
ds.insert((*it)->first, str);
|
||||
}
|
||||
else if (obj->isArray((*it)->first))
|
||||
{
|
||||
Array::Ptr pArr = obj->getArray((*it)->first);
|
||||
std::vector<Poco::Dynamic::Var> v = Poco::JSON::Array::makeArray(pArr);
|
||||
ds.insert((*it)->first, v);
|
||||
}
|
||||
else
|
||||
ds.insert((*it)->first, (*it)->second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstIterator it = obj->begin();
|
||||
ConstIterator end = obj->end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (obj->isObject(it))
|
||||
{
|
||||
Object::Ptr pObj = obj->getObject(it->first);
|
||||
S str = makeStructImpl<S>(pObj);
|
||||
ds.insert(it->first, str);
|
||||
}
|
||||
else if (obj->isArray(it))
|
||||
{
|
||||
Array::Ptr pArr = obj->getArray(it->first);
|
||||
std::vector<Poco::Dynamic::Var> v = Poco::JSON::Array::makeArray(pArr);
|
||||
ds.insert(it->first, v);
|
||||
}
|
||||
else
|
||||
ds.insert(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
const std::string& getKey(ValueMap::const_iterator& it) const;
|
||||
const Dynamic::Var& getValue(ValueMap::const_iterator& it) const;
|
||||
const std::string& getKey(KeyList::const_iterator& it) const;
|
||||
@ -285,8 +359,11 @@ private:
|
||||
// because Object can be returned stringified from Dynamic::Var::toString(),
|
||||
// so it must know whether to escape unicode or not.
|
||||
bool _escapeUnicode;
|
||||
mutable StructPtr _pStruct;
|
||||
mutable bool _modified;
|
||||
mutable StructPtr _pStruct;
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
mutable OrdStructPtr _pOrdStruct;
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
mutable bool _modified;
|
||||
};
|
||||
|
||||
|
||||
|
@ -220,52 +220,51 @@ Object& Object::set(const std::string& key, const Dynamic::Var& value)
|
||||
|
||||
Poco::DynamicStruct Object::makeStruct(const Object::Ptr& obj)
|
||||
{
|
||||
Poco::DynamicStruct ds;
|
||||
|
||||
ConstIterator it = obj->begin();
|
||||
ConstIterator end = obj->end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (obj->isObject(it))
|
||||
{
|
||||
Object::Ptr pObj = obj->getObject(it->first);
|
||||
DynamicStruct str = makeStruct(pObj);
|
||||
ds.insert(it->first, str);
|
||||
}
|
||||
else if (obj->isArray(it))
|
||||
{
|
||||
Array::Ptr pArr = obj->getArray(it->first);
|
||||
std::vector<Poco::Dynamic::Var> v = Poco::JSON::Array::makeArray(pArr);
|
||||
ds.insert(it->first, v);
|
||||
}
|
||||
else
|
||||
ds.insert(it->first, it->second);
|
||||
}
|
||||
|
||||
return ds;
|
||||
return makeStructImpl<Poco::DynamicStruct>(obj);
|
||||
}
|
||||
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
|
||||
Poco::OrderedDynamicStruct Object::makeOrderedStruct(const Object::Ptr& obj)
|
||||
{
|
||||
return makeStructImpl<Poco::OrderedDynamicStruct>(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
void Object::resetOrdDynStruct() const
|
||||
{
|
||||
if (!_pOrdStruct)
|
||||
_pOrdStruct = new Poco::OrderedDynamicStruct;
|
||||
else
|
||||
_pOrdStruct->clear();
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
/*
|
||||
void Object::resetDynStruct() const
|
||||
{
|
||||
if (!_pStruct)
|
||||
_pStruct = new Poco::DynamicStruct;
|
||||
else
|
||||
_pStruct->clear();
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
Object::operator const Poco::DynamicStruct& () const
|
||||
{
|
||||
if (!_values.size())
|
||||
{
|
||||
resetDynStruct();
|
||||
resetDynStruct(_pStruct);
|
||||
}
|
||||
else if (_modified)
|
||||
{
|
||||
ValueMap::const_iterator it = _values.begin();
|
||||
ValueMap::const_iterator end = _values.end();
|
||||
resetDynStruct();
|
||||
resetDynStruct(_pStruct);
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (isObject(it))
|
||||
@ -287,6 +286,68 @@ Object::operator const Poco::DynamicStruct& () const
|
||||
}
|
||||
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
|
||||
|
||||
void Object::clear()
|
||||
{
|
||||
_values.clear();
|
||||
|
@ -1587,7 +1587,6 @@ void JSONTest::testStringifyPreserveOrder()
|
||||
std::ostringstream ostr;
|
||||
|
||||
Stringifier::condense(result, ostr);
|
||||
std::cout << ostr.str() << std::endl;
|
||||
assertTrue (ostr.str() == "{\"Simpsons\":{\"husband\":{\"name\":\"Homer\",\"age\":38},\"wife\":{\"name\":\"Marge\",\"age\":36},"
|
||||
"\"children\":[\"Bart\",\"Lisa\",\"Maggie\"],"
|
||||
"\"address\":{\"number\":742,\"street\":\"Evergreen Terrace\",\"town\":\"Springfield\"}}}");
|
||||
@ -1674,7 +1673,12 @@ void JSONTest::testStringifyPreserveOrder()
|
||||
"}");
|
||||
|
||||
Poco::DynamicStruct ds = *result.extract<Object::Ptr>();
|
||||
assertTrue(ds.toString() == "{ \"Simpsons\" : { \"address\" : { \"number\" : 742, \"street\" : \"Evergreen Terrace\", \"town\" : \"Springfield\" }, "
|
||||
"\"children\" : [ \"Bart\", \"Lisa\", \"Maggie\" ], "
|
||||
"\"husband\" : { \"age\" : 38, \"name\" : \"Homer\" }, "
|
||||
"\"wife\" : { \"age\" : 36, \"name\" : \"Marge\" } } }");
|
||||
assertTrue (ds["Simpsons"].isStruct());
|
||||
assertFalse(ds["Simpsons"].isOrdered());
|
||||
assertTrue (ds["Simpsons"]["husband"].isStruct());
|
||||
assertTrue (ds["Simpsons"]["husband"]["name"] == "Homer");
|
||||
assertTrue (ds["Simpsons"]["husband"]["age"] == 38);
|
||||
@ -1692,6 +1696,17 @@ void JSONTest::testStringifyPreserveOrder()
|
||||
assertTrue (ds["Simpsons"]["address"]["number"] == 742);
|
||||
assertTrue (ds["Simpsons"]["address"]["street"] == "Evergreen Terrace");
|
||||
assertTrue (ds["Simpsons"]["address"]["town"] == "Springfield");
|
||||
|
||||
#ifdef POCO_ENABLE_CPP11
|
||||
Poco::OrderedDynamicStruct ods = *result.extract<Object::Ptr>();
|
||||
assertTrue(ods["Simpsons"].isStruct());
|
||||
assertTrue(ods["Simpsons"].isOrdered());
|
||||
assertTrue(ods.toString() == "{ \"Simpsons\" : { \"husband\" : { \"name\" : \"Homer\", \"age\" : 38 }, "
|
||||
"\"wife\" : { \"name\" : \"Marge\", \"age\" : 36 }, "
|
||||
"\"children\" : [ \"Bart\", \"Lisa\", \"Maggie\" ], "
|
||||
"\"address\" : { \"number\" : 742, \"street\" : \"Evergreen Terrace\", "
|
||||
"\"town\" : \"Springfield\" } } }");
|
||||
#endif // POCO_ENABLE_CPP11
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user