Var/JSON changes

- JSON support for Dynamic Struct and Array
- added VarIterator
- modified behavior of empty Var
This commit is contained in:
Aleksandar Fabijanic 2013-05-27 21:00:14 -05:00
parent 1f8fcaacc0
commit 38131d452d
42 changed files with 1878 additions and 308 deletions

View File

@ -81,7 +81,7 @@ class Data_API Statement
/// However, calling executAsync() on a synchronous statement shall execute
/// asynchronously but without altering the underlying statement's synchronous nature.
///
/// Once asyncronous, a statement can be reverted back to synchronous state in two ways:
/// Once asynchronous, a statement can be reverted back to synchronous state in two ways:
///
/// 1) By calling setAsync(false)
/// 2) By means of 'sync' or 'reset' manipulators

View File

@ -6813,6 +6813,10 @@
RelativePath=".\include\Poco\Dynamic\VarHolder.h"
>
</File>
<File
RelativePath=".\include\Poco\Dynamic\VarIterator.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -6825,6 +6829,10 @@
RelativePath=".\src\VarHolder.cpp"
>
</File>
<File
RelativePath=".\src\VarIterator.cpp"
>
</File>
</Filter>
</Filter>
</Files>

View File

@ -389,6 +389,7 @@
<ClCompile Include="src\UTF32Encoding.cpp" />
<ClCompile Include="src\Var.cpp" />
<ClCompile Include="src\VarHolder.cpp" />
<ClCompile Include="src\VarIterator.cpp" />
<ClCompile Include="src\Void.cpp" />
<ClCompile Include="src\Base64Decoder.cpp" />
<ClCompile Include="src\Base64Encoder.cpp" />
@ -998,6 +999,7 @@
<ClInclude Include="include\Poco\Dynamic\Struct.h" />
<ClInclude Include="include\Poco\Dynamic\Var.h" />
<ClInclude Include="include\Poco\Dynamic\VarHolder.h" />
<ClInclude Include="include\Poco\Dynamic\VarIterator.h" />
<ClInclude Include="include\Poco\Environment.h" />
<ClInclude Include="include\Poco\Environment_UNIX.h" />
<ClInclude Include="include\Poco\Environment_VMS.h" />

View File

@ -870,6 +870,9 @@
<ClCompile Include="src\VarHolder.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\VarIterator.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Latin2Encoding.cpp">
<Filter>Text\Source Files</Filter>
</ClCompile>
@ -1820,6 +1823,9 @@
<ClInclude Include="include\Poco\Dynamic\VarHolder.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Dynamic\VarIterator.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Windows1250Encoding.h">
<Filter>Text\Header Files</Filter>
</ClInclude>

View File

@ -393,6 +393,7 @@
<ClCompile Include="src\UTF32Encoding.cpp" />
<ClCompile Include="src\Var.cpp" />
<ClCompile Include="src\VarHolder.cpp" />
<ClCompile Include="src\VarIterator.cpp" />
<ClCompile Include="src\Void.cpp" />
<ClCompile Include="src\Base32Decoder.cpp" />
<ClCompile Include="src\Base32Encoder.cpp" />
@ -1002,6 +1003,7 @@
<ClInclude Include="include\Poco\Dynamic\Struct.h" />
<ClInclude Include="include\Poco\Dynamic\Var.h" />
<ClInclude Include="include\Poco\Dynamic\VarHolder.h" />
<ClInclude Include="include\Poco\Dynamic\VarIterator.h" />
<ClInclude Include="include\Poco\Environment.h" />
<ClInclude Include="include\Poco\Environment_UNIX.h" />
<ClInclude Include="include\Poco\Environment_VMS.h" />

View File

@ -888,6 +888,9 @@
<ClCompile Include="src\VarHolder.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Variterator.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Latin2Encoding.cpp">
<Filter>Text\Source Files</Filter>
</ClCompile>
@ -1850,6 +1853,9 @@
<ClInclude Include="include\Poco\Dynamic\VarHolder.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Dynamic\VarIterator.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Windows1250Encoding.h">
<Filter>Text\Header Files</Filter>
</ClInclude>

View File

@ -4700,6 +4700,9 @@
<File
RelativePath=".\src\VarHolder.cpp">
</File>
<File
RelativePath=".\src\VarIterator.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
@ -4716,6 +4719,9 @@
<File
RelativePath=".\include\poco\dynamic\VarHolder.h">
</File>
<File
RelativePath=".\include\poco\dynamic\VarIterator.h">
</File>
</Filter>
</Filter>
<File

View File

@ -6101,6 +6101,10 @@
RelativePath=".\include\Poco\Dynamic\VarHolder.h"
>
</File>
<File
RelativePath=".\include\Poco\Dynamic\VarIterator.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -6113,6 +6117,10 @@
RelativePath=".\src\VarHolder.cpp"
>
</File>
<File
RelativePath=".\src\VarIterator.cpp"
>
</File>
</Filter>
</Filter>
<File

View File

@ -6094,6 +6094,10 @@
RelativePath=".\include\Poco\Dynamic\VarHolder.h"
>
</File>
<File
RelativePath=".\include\Poco\Dynamic\VarIterator.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -6106,6 +6110,10 @@
RelativePath=".\src\VarHolder.cpp"
>
</File>
<File
RelativePath=".\src\VarIterator.cpp"
>
</File>
</Filter>
</Filter>
<File

View File

@ -393,6 +393,7 @@
<ClCompile Include="src\UTF32Encoding.cpp" />
<ClCompile Include="src\Var.cpp" />
<ClCompile Include="src\VarHolder.cpp" />
<ClCompile Include="src\VarIterator.cpp" />
<ClCompile Include="src\Void.cpp" />
<ClCompile Include="src\Base32Decoder.cpp" />
<ClCompile Include="src\Base32Encoder.cpp" />
@ -1001,6 +1002,7 @@
<ClInclude Include="include\Poco\Dynamic\Struct.h" />
<ClInclude Include="include\Poco\Dynamic\Var.h" />
<ClInclude Include="include\Poco\Dynamic\VarHolder.h" />
<ClInclude Include="include\Poco\Dynamic\VarIterator.h" />
<ClInclude Include="include\Poco\Environment.h" />
<ClInclude Include="include\Poco\Environment_UNIX.h" />
<ClInclude Include="include\Poco\Environment_VMS.h" />

View File

@ -891,6 +891,9 @@
<ClCompile Include="src\VarHolder.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\VarIterator.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Latin2Encoding.cpp">
<Filter>Text\Source Files</Filter>
</ClCompile>
@ -1853,6 +1856,9 @@
<ClInclude Include="include\Poco\Dynamic\VarHolder.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Dynamic\VarIterator.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Latin2Encoding.h">
<Filter>Text\Header Files</Filter>
</ClInclude>

View File

@ -399,6 +399,7 @@
<ClCompile Include="src\UTF32Encoding.cpp" />
<ClCompile Include="src\Var.cpp" />
<ClCompile Include="src\VarHolder.cpp" />
<ClCompile Include="src\VarIterator.cpp" />
<ClCompile Include="src\Void.cpp" />
<ClCompile Include="src\Base32Decoder.cpp" />
<ClCompile Include="src\Base32Encoder.cpp" />
@ -1007,6 +1008,7 @@
<ClInclude Include="include\Poco\Dynamic\Struct.h" />
<ClInclude Include="include\Poco\Dynamic\Var.h" />
<ClInclude Include="include\Poco\Dynamic\VarHolder.h" />
<ClInclude Include="include\Poco\Dynamic\VarIterator.h" />
<ClInclude Include="include\Poco\Environment.h" />
<ClInclude Include="include\Poco\Environment_UNIX.h" />
<ClInclude Include="include\Poco\Environment_VMS.h" />

View File

@ -891,6 +891,9 @@
<ClCompile Include="src\VarHolder.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\VarIterator.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Latin2Encoding.cpp">
<Filter>Text\Source Files</Filter>
</ClCompile>
@ -1853,6 +1856,9 @@
<ClInclude Include="include\Poco\Dynamic\VarHolder.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Dynamic\VarIterator.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Latin2Encoding.h">
<Filter>Text\Header Files</Filter>
</ClInclude>

View File

@ -6096,6 +6096,10 @@
RelativePath=".\include\Poco\Dynamic\VarHolder.h"
>
</File>
<File
RelativePath=".\include\Poco\Dynamic\VarIterator.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -6108,6 +6112,10 @@
RelativePath=".\src\VarHolder.cpp"
>
</File>
<File
RelativePath=".\src\VarIterator.cpp"
>
</File>
</Filter>
</Filter>
<File

View File

@ -73,13 +73,13 @@ public:
}
template <typename T>
Pair(const std::pair<K, T>& val): _data(std::make_pair(val.first, Var(val.second)))
Pair(const std::pair<K, T>& val): _data(std::make_pair(val.first, val.second))
/// Creates Pair form standard pair.
{
}
template <typename T>
Pair(const K& first, const T& second): _data(std::make_pair(first, Var(second)))
Pair(const K& first, const T& second): _data(std::make_pair(first, second))
/// Creates pair from two values.
{
}
@ -90,15 +90,10 @@ public:
}
Pair& swap(Pair& other)
/// Swaps the content of the two Pairs.
{
std::swap(_data, other._data);
return *this;
}
Pair& operator = (const Pair& other)
@ -215,9 +210,9 @@ public:
// JSON format definition: { string ':' value } string:value pair n-times, sep. by ','
val.append("{ ");
Var key(_val.first());
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, _val.second());
Impl::appendJSONValue(val, _val.second());
val.append(" }");
}
@ -364,9 +359,9 @@ public:
// JSON format definition: { string ':' value } string:value pair n-times, sep. by ','
val.append("{ ");
Var key(_val.first());
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, _val.second());
Impl::appendJSONValue(val, _val.second());
val.append(" }");
}

View File

@ -43,6 +43,7 @@
#include "Poco/Foundation.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Dynamic/VarHolder.h"
#include "Poco/SharedPtr.h"
#include <map>
#include <set>
@ -63,6 +64,7 @@ public:
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 SharedPtr<Struct<K> > Ptr;
Struct(): _data()
/// Creates an empty Struct
@ -148,7 +150,8 @@ public:
return _data.begin();
}
inline InsRetVal insert(const K& key, const Var& value)
template <typename T>
inline InsRetVal insert(const K& key, const T& value)
/// Inserts a <name, Var> pair into the Struct,
/// returns a pair containing the iterator and a boolean which
/// indicates success or not (is true, when insert succeeded, false,
@ -156,7 +159,7 @@ public:
/// points to that other element)
{
// fix: SunPro C++ is silly ...
ValueType valueType(key,value);
ValueType valueType(key, value);
return insert(valueType);
}
@ -301,18 +304,18 @@ public:
if (!_val.empty())
{
Var key(it->first);
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, it->second);
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, it->second);
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
}
@ -372,6 +375,11 @@ public:
return false;
}
std::size_t size() const
{
return _val.size();
}
Var& operator [] (const std::string& name)
{
return _val[name];
@ -472,18 +480,18 @@ public:
if (!_val.empty())
{
Var key(it->first);
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, it->second);
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
appendJSONKey(val, key);
Impl::appendJSONKey(val, key);
val.append(" : ");
appendJSONValue(val, it->second);
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
}
@ -543,6 +551,11 @@ public:
return false;
}
std::size_t size() const
{
return _val.size();
}
Var& operator [] (int name)
{
return _val[name];
@ -561,7 +574,6 @@ private:
} // namespace Dynamic
//@ deprecated
typedef Dynamic::Struct<std::string> DynamicStruct;

View File

@ -42,7 +42,9 @@
#include "Poco/Foundation.h"
#include "Poco/Format.h"
#include "Poco/SharedPtr.h"
#include "Poco/Dynamic/VarHolder.h"
#include "Poco/Dynamic/VarIterator.h"
#include <typeinfo>
@ -97,6 +99,10 @@ class Foundation_API Var
/// VarHolderImpl is available. For supported types, see VarHolder documentation.
{
public:
typedef SharedPtr<Var> Ptr;
typedef Poco::Dynamic::VarIterator Iterator;
typedef const VarIterator ConstIterator;
Var();
/// Creates an empty Var.
@ -104,8 +110,14 @@ public:
Var(const T& val)
/// Creates the Var from the given value.
#ifdef POCO_NO_SOO
:_pHolder(new VarHolderImpl<T>(val)) { }
: _pHolder(new VarHolderImpl<T>(val)),
_pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
}
#else
: _pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
construct(val);
}
@ -123,6 +135,18 @@ public:
void swap(Var& other);
/// Swaps the content of the this Var with the other Var.
ConstIterator& begin() const;
/// Returns the const Var iterator.
ConstIterator& end() const;
/// Returns the const Var iterator.
Iterator begin();
/// Returns the Var iterator.
Iterator end();
/// Returns the Var iterator.
template <typename T>
void convert(T& val) const
/// Invoke this method to perform a safe conversion.
@ -427,49 +451,45 @@ public:
template <typename T>
bool operator && (const T& other) const
/// Logical AND operator
/// Logical AND operator.
{
if (isEmpty()) return false;
return convert<bool>() && other;
}
bool operator && (const Var& other) const;
/// Logical AND operator operator overload for Var
/// Logical AND operator operator overload for Var.
bool isArray() const;
/// Returns true if Var represents a vector
/// Returns true if Var is not empty.
bool isVector() const;
/// Returns true if Var represents a vector.
bool isList() const;
/// Returns true if Var represents a list.
bool isDeque() const;
/// Returns true if Var represents a deque.
bool isStruct() const;
/// Returns true if Var represents a struct
/// Returns true if Var represents a struct.
char& at(std::size_t n);
/// Returns character at position n. This function only works with
/// Var containing a std::string.
template <typename T>
Var& operator [] (T n)
/// Index operator, only use on Vars where isArray() or isStruct()
/// returns true! In all other cases InvalidAccessException is thrown.
Var& operator [] (const T& n)
{
if (isArray())
return holderImpl<std::vector<Var>,
InvalidAccessException>("Not an array.")->operator[](n);
else if (isStruct())
return structIndexOperator(holderImpl<Struct<int>,
InvalidAccessException>("Not a struct."), static_cast<int>(n));
else
throw InvalidAccessException("Must be struct or array.");
return getAt(n);
}
template <typename T>
const Var& operator [] (T n) const
/// const Index operator, only use on Vars where isArray() or isStruct()
/// returns true! In all other cases InvalidAccessException is thrown.
const Var& operator [] (const T& n) const
{
if (isArray())
return holderImpl<std::vector<Var>,
InvalidAccessException>("Not an array.")->operator[](n);
else if (isStruct())
return structIndexOperator(holderImpl<Struct<int>,
InvalidAccessException>("Not a struct."), static_cast<int>(n));
else
throw InvalidAccessException("Must be struct or array.");
return const_cast<Var*>(this)->getAt(n);
}
Var& operator [] (const std::string& name);
@ -480,14 +500,6 @@ public:
/// Index operator by name, only use on Vars where isStruct
/// returns true! In all other cases InvalidAccessException is thrown.
Var& operator [] (const char* name);
/// Index operator by name, only use on Vars where isStruct
/// returns true! In all other cases InvalidAccessException is thrown.
const Var& operator [] (const char* name) const;
/// Index operator by name, only use on Vars where isStruct
/// returns true! In all other cases InvalidAccessException is thrown.
const std::type_info& type() const;
/// Returns the type information of the stored content.
@ -510,6 +522,11 @@ public:
bool isString() const;
/// Returns true if stored value is std::string.
std::size_t Var::size() const;
/// Returns the size of this Var.
/// This function returns 0 when Var is empty, 1 for POD or the size (i.e. length)
/// for held container.
std::string toString() const
/// Returns the stored value as string.
{
@ -536,6 +553,9 @@ public:
/// a different result than Var::convert<std::string>() and Var::toString()!
private:
Var& getAt(std::size_t n);
Var& getAt(const std::string& n);
static Var parse(const std::string& val, std::string::size_type& offset);
/// Parses the string which must be in JSON format
@ -657,6 +677,8 @@ private:
#endif // POCO_NO_SOO
Iterator* _pBegin;
Iterator* _pEnd;
};
@ -710,15 +732,42 @@ inline const std::type_info& Var::type() const
}
inline Var& Var::operator [] (const char* name)
inline Var::ConstIterator& Var::begin() const
{
return operator [] (std::string(name));
if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
return *_pBegin;
}
inline Var::ConstIterator& Var::end() const
{
return *_pEnd;
}
inline Var::Iterator Var::begin()
{
if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
return *_pBegin;
}
inline Var::Iterator Var::end()
{
return *_pEnd;
}
inline const Var& Var::operator [] (const char* name) const
inline Var& Var::operator [] (const std::string& name)
{
return operator [] (std::string(name));
return getAt(name);
}
inline const Var& Var::operator [] (const std::string& name) const
{
return const_cast<Var*>(this)->getAt(name);
}
@ -747,9 +796,29 @@ inline bool Var::isEmpty() const
inline bool Var::isArray() const
{
return !isEmpty() && !isString();
}
inline bool Var::isVector() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isArray() : false;
return pHolder ? pHolder->isVector() : false;
}
inline bool Var::isList() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isList() : false;
}
inline bool Var::isDeque() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isDeque() : false;
}
@ -788,6 +857,13 @@ inline bool Var::isString() const
}
inline std::size_t Var::size() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->size() : 0;
}
///
/// Var non-member functions
///

View File

@ -53,6 +53,8 @@
#include "Poco/Any.h"
#include "Poco/Exception.h"
#include <vector>
#include <list>
#include <deque>
#include <typeinfo>
#undef min
#undef max
@ -66,6 +68,9 @@ namespace Dynamic {
class Var;
namespace Impl {
bool Foundation_API isJSONString(const Var& any);
/// Returns true for values that should be JSON-formatted as string.
@ -86,6 +91,35 @@ void Foundation_API appendJSONValue(std::string& val, const Var& any);
/// and appends it to val
template <typename C>
void containerToJSON(C& cont, std::string& val)
{
// Serialize in JSON format. Note: although this is a vector<T>, the code only
// supports vector<Var>. Total specialization is not possible
// because of the cyclic dependency between Var and VarHolder
// JSON format definition: [ n times: elem ',' ], no ',' for last elem
val.append("[ ");
typename C::const_iterator it = cont.begin();
typename C::const_iterator itEnd = cont.end();
if (!cont.empty())
{
appendJSONValue(val, *it);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
appendJSONValue(val, *it);
}
val.append(" ]");
}
} // namespace Impl
class Foundation_API VarHolder
/// Interface for a data holder used by the Var class.
/// Provides methods to convert between data types.
@ -103,6 +137,8 @@ class Foundation_API VarHolder
/// throw BadCastException.
{
public:
typedef Var ArrayValueType;
virtual ~VarHolder();
/// Destroys the VarHolder.
@ -193,6 +229,17 @@ public:
/// specialization in order to suport the conversion.
virtual bool isArray() const;
/// Returns true.
virtual bool isVector() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual bool isList() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual bool isDeque() const;
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
@ -216,6 +263,9 @@ public:
/// Returns false. Must be properly overriden in a type
/// specialization in order to suport the diagnostic.
virtual std::size_t size() const;
/// Returns 1 iff Var is not empty or this function overriden.
protected:
VarHolder();
/// Creates the VarHolder.
@ -504,6 +554,24 @@ inline void VarHolder::convert(std::string& /*val*/) const
inline bool VarHolder::isArray() const
{
return true;
}
inline bool VarHolder::isVector() const
{
return false;
}
inline bool VarHolder::isList() const
{
return false;
}
inline bool VarHolder::isDeque() const
{
return false;
}
@ -537,6 +605,11 @@ inline bool VarHolder::isString() const
return false;
}
inline std::size_t VarHolder::size() const
{
return 1u;
}
template <typename T>
class VarHolderImpl: public VarHolder
@ -2226,8 +2299,8 @@ private:
};
template <>
class VarHolderImpl<std::string>: public VarHolder
template <typename T>
class VarHolderImpl<std::basic_string<T> >: public VarHolder
{
public:
VarHolderImpl(const char* pVal): _val(pVal)
@ -2366,42 +2439,36 @@ public:
return _val;
}
bool isArray() const
{
return false;
}
bool isStruct() const
{
return false;
}
bool isInteger() const
{
return false;
}
bool isSigned() const
{
return false;
}
bool isNumeric() const
{
return false;
}
bool isString() const
{
return true;
}
std::size_t size() const
{
return _val.length();
}
T& operator[](std::string::size_type n)
{
if (n < size()) return _val.operator[](n);
throw RangeException("String index out of range");
}
const T& operator[](std::string::size_type n) const
{
if (n < size()) return _val.operator[](n);
throw RangeException("String index out of range");
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
VarHolderImpl& operator = (const VarHolderImpl&);
std::string _val;
std::basic_string<T> _val;
};
@ -2696,26 +2763,7 @@ public:
void convert(std::string& val) const
{
// Serialize in JSON format: note: although this is a vector<T>, the code only
// supports vector<Var>. Total specialization is not possible
// because of the cyclic dependency between Var and VarHolder
// JSON format definition: [ n times: elem ',' ], no ',' for last elem
val.append("[ ");
typename std::vector<T>::const_iterator it = _val.begin();
typename std::vector<T>::const_iterator itEnd = _val.end();
if (!_val.empty())
{
appendJSONValue(val, *it);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
appendJSONValue(val, *it);
}
val.append(" ]");
Impl::containerToJSON(_val, val);
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
@ -2728,44 +2776,28 @@ public:
return _val;
}
bool isArray() const
bool isVector() const
{
return true;
}
bool isStruct() const
std::size_t size() const
{
return false;
}
bool isInteger() const
{
return false;
}
bool isSigned() const
{
return false;
}
bool isNumeric() const
{
return false;
}
bool isString() const
{
return false;
return _val.size();
}
T& operator[](typename std::vector<T>::size_type n)
{
return _val.operator[](n);
if (n < size()) return _val.operator[](n);
throw RangeException("List index out of range");
}
const T& operator[](typename std::vector<T>::size_type n) const
{
return _val.operator[](n);
if (n < size()) return _val.operator[](n);
throw RangeException("List index out of range");
}
private:
@ -2777,6 +2809,146 @@ private:
};
template <typename T>
class VarHolderImpl<std::list<T> >: public VarHolder
{
public:
VarHolderImpl(const std::list<T>& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(std::list<T>);
}
void convert(std::string& val) const
{
Impl::containerToJSON(_val, val);
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const std::list<T>& value() const
{
return _val;
}
bool isList() const
{
return true;
}
std::size_t size() const
{
return _val.size();
}
T& operator[](typename std::list<T>::size_type n)
{
if (n >= size())
throw RangeException("List index out of range");
std::list<T>::size_type counter = 0;
std::list<T>::iterator it = _val.begin();
for (; counter < n; ++counter) ++it;
return *it;
}
const T& operator[](typename std::list<T>::size_type n) const
{
if (n >= size())
throw RangeException("List index out of range");
std::list<T>::size_type counter = 0;
std::list<T>::const_iterator it = _val.begin();
for (; counter < n; ++counter) ++it;
return *it;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
VarHolderImpl& operator = (const VarHolderImpl&);
std::list<T> _val;
};
template <typename T>
class VarHolderImpl<std::deque<T> >: public VarHolder
{
public:
VarHolderImpl(const std::deque<T>& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(std::deque<T>);
}
void convert(std::string& val) const
{
Impl::containerToJSON(_val, val);
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const std::deque<T>& value() const
{
return _val;
}
bool isDeque() const
{
return true;
}
std::size_t size() const
{
return _val.size();
}
T& operator[](typename std::deque<T>::size_type n)
{
if (n < size()) return _val.operator[](n);
throw RangeException("List index out of range");
}
const T& operator[](typename std::deque<T>::size_type n) const
{
if (n < size()) return _val.operator[](n);
throw RangeException("List index out of range");
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
VarHolderImpl& operator = (const VarHolderImpl&);
std::deque<T> _val;
};
template <>
class VarHolderImpl<DateTime>: public VarHolder
{
@ -3080,6 +3252,12 @@ private:
};
typedef std::vector<Var> Vector;
typedef std::deque<Var> Deque;
typedef std::list<Var> List;
typedef Vector Array;
} } // namespace Poco::Dynamic

View File

@ -0,0 +1,173 @@
//
// VarIterator.h
//
// $Id: //poco/Main/Foundation/include/Poco/Dynamic/VarIterator.h#1 $
//
// Library: Foundation
// Package: Dynamic
// Module: VarIterator
//
// Definition of the VarIterator class.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef Foundation_VarIterator_INCLUDED
#define Foundation_VarIterator_INCLUDED
#include "Poco/Exception.h"
#include <iterator>
#include <algorithm>
namespace Poco {
namespace Dynamic {
class Var;
class Foundation_API VarIterator
/// VarIterator class.
{
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef Var value_type;
typedef std::ptrdiff_t difference_type;
typedef Var* pointer;
typedef Var& reference;
static const int POSITION_END;
/// End position indicator.
VarIterator(Var* pVar, bool positionEnd);
/// Creates the VarIterator and positions it at the end of
/// the recordset if positionEnd is true. Otherwise, it is
/// positioned at the beginning.
VarIterator(const VarIterator& other);
/// Creates a copy of other VarIterator.
~VarIterator();
/// Destroys the VarIterator.
VarIterator& operator = (const VarIterator& other);
/// Assigns the other VarIterator.
bool operator == (const VarIterator& other) const;
/// Equality operator.
bool operator != (const VarIterator& other) const;
/// Inequality operator.
Var& operator * () const;
/// Returns value at the current position.
Var* operator -> () const;
/// Returns pointer to the value at current position.
const VarIterator& operator ++ () const;
/// Advances by one position and returns current position.
VarIterator operator ++ (int) const;
/// Advances by one position and returns copy of the iterator with
/// previous current position.
const VarIterator& operator -- () const;
/// Goes back by one position and returns copy of the iterator with
/// previous current position.
VarIterator operator -- (int) const;
/// Goes back by one position and returns previous current position.
VarIterator operator + (std::size_t diff) const;
/// Returns a copy the VarIterator advanced by diff positions.
VarIterator operator - (std::size_t diff) const;
/// Returns a copy the VarIterator backed by diff positions.
/// Throws RangeException if diff is larger than current position.
void swap(VarIterator& other);
/// Swaps the VarIterator with another one.
private:
VarIterator();
void increment() const;
/// Increments the iterator position by one.
/// Throws RangeException if position is out of range.
void decrement() const;
/// Decrements the iterator position by one.
/// Throws RangeException if position is out of range.
void setPosition(std::size_t pos) const;
/// Sets the iterator position.
/// Throws RangeException if position is out of range.
Var* _pVar;
mutable std::size_t _position;
friend class Var;
};
///
/// inlines
///
inline bool VarIterator::operator == (const VarIterator& other) const
{
return _pVar == other._pVar && _position == other._position;
}
inline bool VarIterator::operator != (const VarIterator& other) const
{
return _pVar != other._pVar || _position != other._position;
}
} } // namespace Poco::Dynamic
namespace std
{
using std::swap;
template<>
inline void swap<Poco::Dynamic::VarIterator>(Poco::Dynamic::VarIterator& s1,
Poco::Dynamic::VarIterator& s2)
/// Full template specalization of std:::swap for VarIterator
{
s1.swap(s2);
}
}
#endif // Foundation_VarIterator_INCLUDED

View File

@ -38,24 +38,35 @@
#include "Poco/Dynamic/Struct.h"
#include <algorithm>
#include <cctype>
#include <vector>
#include <list>
#include <deque>
namespace Poco {
namespace Dynamic {
Var::Var()
Var::Var() :
#ifdef POCO_NO_SOO
: _pHolder(0)
_pHolder(0),
#endif
_pBegin(new Iterator(this, true)),
_pEnd(new Iterator(this, true))
{
}
Var::Var(const char* pVal)
#ifdef POCO_NO_SOO
: _pHolder(new VarHolderImpl<std::string>(pVal)) { }
: _pHolder(new VarHolderImpl<std::string>(pVal)),
_pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
}
#else
: _pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
construct(std::string(pVal));
}
@ -64,12 +75,14 @@ Var::Var(const char* pVal)
Var::Var(const Var& other)
#ifdef POCO_NO_SOO
: _pHolder(0)
: _pHolder(other._pHolder ? other._pHolder->clone() : 0),
_pBegin(new Iterator(*other._pBegin)),
_pEnd(new Iterator(*other._pEnd))
{
if (other._pHolder)
_pHolder = other._pHolder->clone();
}
#else
: _pBegin(new Iterator(*other._pBegin)),
_pEnd(new Iterator(*other._pEnd))
{
if ((this != &other) && !other.isEmpty())
construct(other);
@ -238,6 +251,7 @@ Var& Var::operator ++ ()
return *this = *this + 1;
}
const Var Var::operator ++ (int)
{
if (!isInteger())
@ -248,6 +262,7 @@ const Var Var::operator ++ (int)
return tmp;
}
Var& Var::operator -- ()
{
if (!isInteger())
@ -256,6 +271,7 @@ Var& Var::operator -- ()
return *this = *this - 1;
}
const Var Var::operator -- (int)
{
if (!isInteger())
@ -269,7 +285,8 @@ const Var Var::operator -- (int)
bool Var::operator == (const Var& other) const
{
if (isEmpty() || other.isEmpty()) return false;
if (isEmpty() && !other.isEmpty()) return false;
if (isEmpty() && other.isEmpty()) return true;
return convert<std::string>() == other.convert<std::string>();
}
@ -352,16 +369,43 @@ void Var::empty()
}
Var& Var::operator [] (const std::string& name)
Var& Var::getAt(std::size_t n)
{
return holderImpl<DynamicStruct, InvalidAccessException>("Not an array.")->operator[](name);
if (isVector())
return holderImpl<std::vector<Var>,
InvalidAccessException>("Not a vector.")->operator[](n);
else if (isList())
return holderImpl<std::list<Var>,
InvalidAccessException>("Not a list.")->operator[](n);
else if (isDeque())
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));
else if (!isString() && !isEmpty() && (n == 0))
return *this;
throw RangeException("Index out of bounds.");
}
const Var& Var::operator [] (const std::string& name) const
char& Var::at(std::size_t n)
{
return const_cast<const Var&>(holderImpl<DynamicStruct,
InvalidAccessException>("Not an array.")->operator[](name));
if (isString())
{
return holderImpl<std::string,
InvalidAccessException>("Not a string.")->operator[](n);
}
throw InvalidAccessException("Not a string.");
}
Var& Var::getAt(const std::string& name)
{
return holderImpl<DynamicStruct,
InvalidAccessException>("Not a struct.")->operator[](name);
}
@ -499,7 +543,7 @@ void Var::skipWhiteSpace(const std::string& val, std::string::size_type& pos)
std::string Var::toString(const Var& any)
{
std::string res;
appendJSONValue(res, any);
Impl::appendJSONValue(res, any);
return res;
}

View File

@ -52,6 +52,9 @@ VarHolder::~VarHolder()
}
namespace Impl {
bool isJSONString(const Var& any)
{
return any.type() == typeid(std::string) ||
@ -90,4 +93,7 @@ void appendJSONValue(std::string& val, const Var& any)
}
} // namespace Impl
} } // namespace Poco::Dynamic

View File

@ -0,0 +1,189 @@
//
// VarIterator.cpp
//
// $Id: //poco/Main/Data/src/VarIterator.cpp#1 $
//
// Library: Foundation
// Package: Dynamic
// Module: VarIterator
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Dynamic/VarIterator.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Dynamic/Struct.h"
#undef min
#undef max
#include <limits>
namespace Poco {
namespace Dynamic {
const int VarIterator::POSITION_END = std::numeric_limits<std::size_t>::max();
VarIterator::VarIterator(Var* pVar, bool positionEnd):
_pVar(pVar),
_position(positionEnd ? POSITION_END : 0)
{
}
VarIterator::VarIterator(const VarIterator& other):
_pVar(other._pVar),
_position(other._position)
{
}
VarIterator::~VarIterator()
{
}
VarIterator& VarIterator::operator = (const VarIterator& other)
{
VarIterator tmp(other);
swap(tmp);
return *this;
}
void VarIterator::swap(VarIterator& other)
{
using std::swap;
swap(_pVar, other._pVar);
swap(_position, other._position);
}
void VarIterator::increment() const
{
if (POSITION_END == _position)
throw RangeException("End of iterator reached.");
if (_position < _pVar->size() - 1)
++_position;
else
_position = POSITION_END;
}
void VarIterator::decrement() const
{
if (0 == _position)
throw RangeException("Beginning of iterator reached.");
else if (POSITION_END == _position)
_position = _pVar->size() - 1;
else
--_position;
}
void VarIterator::setPosition(std::size_t pos) const
{
if (_position == pos) return;
if (pos < _pVar->size())
_position = pos;
else if (pos == _pVar->size())
_position = POSITION_END;
else
throw RangeException("Invalid position argument.");
}
Var& VarIterator::operator * () const
{
if (POSITION_END == _position)
throw InvalidAccessException("End of iterator reached.");
return _pVar->operator[](_position);
}
Var* VarIterator::operator -> () const
{
if (POSITION_END == _position)
throw InvalidAccessException("End of iterator reached.");
return &_pVar->operator[](_position);
}
const VarIterator& VarIterator::operator ++ () const
{
increment();
return *this;
}
VarIterator VarIterator::operator ++ (int) const
{
VarIterator old(*this);
increment();
return old;
}
const VarIterator& VarIterator::operator -- () const
{
decrement();
return *this;
}
VarIterator VarIterator::operator -- (int) const
{
VarIterator old(*this);
decrement();
return old;
}
VarIterator VarIterator::operator + (std::size_t diff) const
{
VarIterator ri(*this);
ri.setPosition(_position + diff);
return ri;
}
VarIterator VarIterator::operator - (std::size_t diff) const
{
if (diff > _position) throw RangeException("Invalid position argument.");
VarIterator ri(*this);
ri.setPosition(_position - diff);
return ri;
}
} } // namespace Poco::Dynamic

View File

@ -1841,6 +1841,7 @@ void VarTest::testIsArray()
std::vector<Var> s16;
DynamicStruct s17;
Var d0;
Var d1(s1);
Var d2(s2);
Var d3(s3);
@ -1859,23 +1860,24 @@ void VarTest::testIsArray()
Var d16(s16);
Var d17(s17);
assert (!d0.isArray());
assert (!d1.isArray());
assert (!d2.isArray());
assert (!d3.isArray());
assert (!d4.isArray());
assert (!d5.isArray());
assert (!d6.isArray());
assert (!d7.isArray());
assert (!d8.isArray());
assert (!d9.isArray());
assert (!d10.isArray());
assert (!d11.isArray());
assert (!d12.isArray());
assert (!d13.isArray());
assert (!d14.isArray());
assert (!d15.isArray());
assert (d2.isArray());
assert (d3.isArray());
assert (d4.isArray());
assert (d5.isArray());
assert (d6.isArray());
assert (d7.isArray());
assert (d8.isArray());
assert (d9.isArray());
assert (d10.isArray());
assert (d11.isArray());
assert (d12.isArray());
assert (d13.isArray());
assert (d14.isArray());
assert (d15.isArray());
assert (d16.isArray());
assert (!d17.isArray());
assert (d17.isArray());
}
@ -1920,23 +1922,39 @@ void VarTest::testArrayIdxOperator()
Var d17(s17);
testGetIdxMustThrow(d1, 0);
testGetIdxMustThrow(d2, 0);
testGetIdxMustThrow(d3, 0);
testGetIdxMustThrow(d4, 0);
testGetIdxMustThrow(d5, 0);
testGetIdxMustThrow(d6, 0);
testGetIdxMustThrow(d7, 0);
testGetIdxMustThrow(d8, 0);
testGetIdxMustThrow(d9, 0);
testGetIdxMustThrow(d10, 0);
testGetIdxMustThrow(d11, 0);
testGetIdxMustThrow(d12, 0);
testGetIdxMustThrow(d13, 0);
testGetIdxMustThrow(d14, 0);
testGetIdxMustThrow(d15, 0);
testGetIdxNoThrow(d2, 0);
testGetIdxNoThrow(d3, 0);
testGetIdxNoThrow(d4, 0);
testGetIdxNoThrow(d5, 0);
testGetIdxNoThrow(d6, 0);
testGetIdxNoThrow(d7, 0);
testGetIdxNoThrow(d8, 0);
testGetIdxNoThrow(d9, 0);
testGetIdxNoThrow(d10, 0);
testGetIdxNoThrow(d11, 0);
testGetIdxNoThrow(d12, 0);
testGetIdxNoThrow(d13, 0);
testGetIdxNoThrow(d14, 0);
testGetIdxNoThrow(d15, 0);
testGetIdx(d16, 0, s1);
testGetIdx(d16, 1, s2);
testGetIdxMustThrow(d17, 0);
testGetIdxMustThrow(d1, 1);
testGetIdxMustThrow(d2, 1);
testGetIdxMustThrow(d3, 1);
testGetIdxMustThrow(d4, 1);
testGetIdxMustThrow(d5, 1);
testGetIdxMustThrow(d6, 1);
testGetIdxMustThrow(d7, 1);
testGetIdxMustThrow(d8, 1);
testGetIdxMustThrow(d9, 1);
testGetIdxMustThrow(d10, 1);
testGetIdxMustThrow(d11, 1);
testGetIdxMustThrow(d12, 1);
testGetIdxMustThrow(d13, 1);
testGetIdxMustThrow(d14, 1);
testGetIdxMustThrow(d15, 1);
testGetIdxMustThrow(d17, 1);
}
@ -2001,9 +2019,9 @@ void VarTest::testDynamicStructInt()
aStruct[1] = "POCO";
aStruct[2] = 10;
Var a1(aStruct);
assert (a1[0] == "Junior");
assert (a1[1] == "POCO");
assert (a1[2] == 10);
assert (a1[0]== "Junior");
assert (a1[1]== "POCO");
assert (a1[2]== 10);
a1[0] = "Senior";
assert (a1[0] == "Senior");
@ -2372,17 +2390,27 @@ void VarTest::testDate()
assert (tsNow == tsRes);
}
void VarTest::testGetIdxNoThrow(Var& a1, std::vector<Var>::size_type n)
{
Var val1 = a1[n];
}
void VarTest::testGetIdxMustThrow(Var& a1, std::vector<Var>::size_type n)
{
try
{
Var& val1 = a1[n];
Var val1 = a1[n];
fail("bad cast - must throw");
val1 = 0; // silence the compiler
}
catch (Poco::InvalidAccessException&)
{
}
catch (Poco::RangeException&)
{
}
try
{
@ -2394,6 +2422,9 @@ void VarTest::testGetIdxMustThrow(Var& a1, std::vector<Var>::size_type n)
catch (Poco::InvalidAccessException&)
{
}
catch (Poco::RangeException&)
{
}
}
@ -2407,7 +2438,7 @@ void VarTest::testEmpty()
assert (!da.isNumeric());
assert (!da.isSigned());
assert (!da.isString());
assert (!(da == da));
assert (da == da);
assert (!(da != da));
da = "123";
@ -2424,7 +2455,7 @@ void VarTest::testEmpty()
assert (!da.isNumeric());
assert (!da.isSigned());
assert (!da.isString());
assert (!(da == da));
assert (da == da);
assert (!(da != da));
assert (da != "");
@ -2432,7 +2463,6 @@ void VarTest::testEmpty()
assert (!(da == ""));
assert (!("" == da));
testEmptyComparisons<unsigned char>();
testEmptyComparisons<char>();
testEmptyComparisons<Poco::UInt8>();
@ -2464,6 +2494,71 @@ void VarTest::testEmpty()
}
void VarTest::testIterator()
{
Var da;
assert (da.isEmpty());
assert (da.begin() == da.end());
da = 1;
assert (!da.isEmpty());
assert (da == 1);
assert (da[0] == 1);
try
{
da[1] = 2;
}
catch (RangeException&) {}
assert (da.begin() != da.end());
Var::Iterator it = da.begin();
Var::Iterator end = da.end();
assert (it != end);
assert (++it == end);
assert (--it == da.begin());
it++;
assert (it == end);
try
{
++it;
fail ("must fail");
}
catch (RangeException&) {}
assert (it == end);
da = "abc";
assert (da.size() == 3);
assert (!da.isArray());
assert (da.isString());
//assert (da[0] == 'a');
assert (da.at(0) == 'a');
//assert (da[1] = 'b');
assert (da.at(1) == 'b');
//assert (da[2] = 'c');
assert (da.at(2) == 'c');
da.at(0) = 'b';
assert (da.at(0) == 'b');
// TODO: allow treatment of strings like arrays
//da[1] = 'c';
da.at(1) = 'c';
assert (da.at(1) == 'c');
//da[2] = 'a';
da.at(2) = 'a';
assert (da.at(2) == 'a');
it = da.begin();
end = da.end();
assert (it != end);
assert (++it != end);
assert (--it == da.begin());
testContainerIterator<std::vector<Var> >();
testContainerIterator<std::list<Var> >();
testContainerIterator<std::deque<Var> >();
}
void VarTest::setUp()
{
}
@ -2518,6 +2613,7 @@ CppUnit::Test* VarTest::suite()
CppUnit_addTest(pSuite, VarTest, testJSONDeserializeComplex);
CppUnit_addTest(pSuite, VarTest, testDate);
CppUnit_addTest(pSuite, VarTest, testEmpty);
CppUnit_addTest(pSuite, VarTest, testIterator);
return pSuite;
}

View File

@ -37,6 +37,7 @@
#include "Poco/Foundation.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Dynamic/VarIterator.h"
#include "Poco/Exception.h"
#include "CppUnit/TestCase.h"
@ -87,6 +88,7 @@ public:
void testJSONDeserializeComplex();
void testDate();
void testEmpty();
void testIterator();
void setUp();
@ -95,15 +97,16 @@ public:
private:
void testGetIdxMustThrow(Poco::Dynamic::Var& a1, std::vector<Poco::Dynamic::Var>::size_type n);
void testGetIdxNoThrow(Poco::Dynamic::Var& a1, std::vector<Poco::Dynamic::Var>::size_type n);
template<typename T>
void testGetIdx(Poco::Dynamic::Var& a1, std::vector<Poco::Dynamic::Var>::size_type n, const T& expectedResult)
void testGetIdx(const Poco::Dynamic::Var& a1, std::vector<Poco::Dynamic::Var>::size_type n, const T& expectedResult)
{
Poco::Dynamic::Var& val1 = a1[n];
Poco::Dynamic::Var val1 = a1[n];
assert (val1 == expectedResult);
const Poco::Dynamic::Var& c1 = a1;
const Poco::Dynamic::Var c1 = a1;
assert (a1 == c1); // silence the compiler
const Poco::Dynamic::Var& cval1 = a1[n];
const Poco::Dynamic::Var cval1 = a1[n];
assert (cval1 == expectedResult);
}
@ -181,6 +184,37 @@ private:
assert (!(da >= val));
assert (!(val >= da));
}
template <typename C>
void testContainerIterator()
{
C cont;
cont.push_back(1);
cont.push_back("2");
cont.push_back(3.5);
Var arr(cont);
assert (arr.size() == 3);
Var::Iterator it = arr.begin();
Var::Iterator end = arr.end();
int counter = 0;
for (; it != end; ++it)
{
switch (++counter)
{
case 1:
assert (*it == 1);
break;
case 2:
assert (*it == 2);
break;
case 3:
assert (*it == 3.5);
break;
default:
fail ("must fail - wrong size");
}
}
}
};

View File

@ -12,9 +12,6 @@
<ClCompile Include="src\Array.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ParseHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Handler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -42,6 +39,9 @@
<ClCompile Include="src\TemplateCache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ParseHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Poco\JSON\Array.h">
@ -62,9 +62,6 @@
<ClInclude Include="include\Poco\JSON\Parser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\JSON\ParseHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\JSON\PrintHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -80,5 +77,8 @@
<ClInclude Include="include\Poco\JSON\TemplateCache.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\JSON\ParseHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -11,7 +11,7 @@ include $(POCO_BASE)/build/rules/global
INCLUDE += -I $(POCO_BASE)/JSON/include/Poco/JSON
objects = Array Object Parser Handler Stringifier \
ParseHandler PrintHandler Query JSONException \
VarHandler PrintHandler Query JSONException \
Template TemplateCache
target = PocoJSON

View File

@ -55,9 +55,34 @@ class Object;
class JSON_API Array
/// Represents a JSON array. JSON array provides a representation
/// based on shared pointers and optimized for performance. It is possible to
/// convert object to Poco::Dynamic::Array. Conversion requires copying and therefore
/// has performance penalty; the benefit is in improved syntax, eg:
///
/// // use pointers to avoid copying
/// using namespace Poco::JSON;
/// std::string json = "[ {\"test\" : 0}, { \"test1\" : [1, 2, 3], \"test2\" : 4 } ]";
/// Parser parser;
/// Var result = parser.parse(json);
/// Array::Ptr arr = result.extract<Array::Ptr>();
/// Object::Ptr object = arr->getObject(0); // object == {\"test\" : 0}
/// int i = object->getValue<int>("test"); // i == 0;
/// Object::Ptr subObject = *arr->getObject(1); // subObject == {\"test\" : 0}
/// Array subArr::Ptr = subObject->getArray("test1"); // subArr == [1, 2, 3]
/// i = result = subArr->get(0); // i == 1;
///
/// // copy/convert to Poco::Dynamic::Array
/// Poco::Dynamic::Array da = *arr;
/// i = da[0]["test"]; // i == 0
/// i = da[1]["test1"][1]; // i == 2
/// i = da[1]["test2"]; // i == 4
///
{
public:
typedef std::vector<Dynamic::Var> ValueVec;
typedef std::vector<Dynamic::Var> ValueVec;
typedef std::vector<Dynamic::Var>::iterator Iterator;
typedef std::vector<Dynamic::Var>::const_iterator ConstIterator;
typedef SharedPtr<Array> Ptr;
Array();
@ -105,6 +130,12 @@ public:
bool isArray(unsigned int index) const;
/// Returns true when the element is an array
bool isArray(const Dynamic::Var& value) const;
/// Returns true when the element is an array
bool isArray(ConstIterator& value) const;
/// Returns true when the element is an array
bool isNull(unsigned int index) const;
/// Returns true when the element is null or
/// when the element doesn't exist.
@ -112,6 +143,12 @@ public:
bool isObject(unsigned int index) const;
/// Returns true when the element is an object
bool isObject(const Dynamic::Var& value) const;
/// Returns true when the element is an object
bool isObject(ConstIterator& value) const;
/// Returns true when the element is an object
template<typename T>
T optElement(unsigned int index, const T& def) const
/// Returns the element at the given index. When
@ -144,8 +181,16 @@ public:
void remove(unsigned int index);
/// Removes the element on the given index.
operator const Poco::Dynamic::Array& () const;
static Poco::Dynamic::Array makeArray(const JSON::Array::Ptr& arr);
/// Utility function for creation of array.
private:
ValueVec _values;
typedef SharedPtr<Poco::Dynamic::Array> ArrayPtr;
ValueVec _values;
mutable ArrayPtr _pArray;
};
@ -171,10 +216,22 @@ inline std::size_t Array::size() const
inline bool Array::isArray(unsigned int index) const
{
Dynamic::Var value = get(index);
return isArray(value);
}
inline bool Array::isArray(const Dynamic::Var& value) const
{
return value.type() == typeid(Array::Ptr);
}
inline bool Array::isArray(ConstIterator& it) const
{
return it!= end() && isArray(*it);
}
inline void Array::add(const Dynamic::Var& value)
{
_values.push_back(value);

View File

@ -43,6 +43,7 @@
#include "Poco/JSON/JSON.h"
#include "Poco/SharedPtr.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Dynamic/Struct.h"
namespace Poco {
@ -60,6 +61,9 @@ public:
virtual ~Handler();
/// Destructor
virtual void reset() = 0;
/// Resets the handler state.
virtual void startObject() = 0;
/// The parser has read a {, meaning a new object will be read
@ -103,10 +107,11 @@ public:
virtual void value(bool b) = 0;
/// A boolean value is read
virtual void comma();
/// A comma is read
virtual Poco::Dynamic::Var asVar() const;
/// Returns the result of the parser (an object, array or string),
/// empty Var if there is no result.
virtual Dynamic::Var result() const;
virtual Poco::DynamicStruct asStruct() const;
/// Returns the result of the parser (an object, array or string),
/// empty Var if there is no result.
};

View File

@ -45,6 +45,7 @@
#include "Poco/JSON/Stringifier.h"
#include "Poco/SharedPtr.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Dynamic/Struct.h"
#include <map>
#include <vector>
#include <deque>
@ -57,10 +58,33 @@ namespace JSON {
class JSON_API Object
/// Represents a JSON object.
/// Represents a JSON object. JSON object provides a representation
/// based on shared pointers and optimized for performance. It is possible to
/// convert object to DynamicStruct. Conversion requires copying and therefore
/// has performance penalty; the benefit is in improved syntax, eg:
///
/// std::string json = "{ \"test\" : { \"property\" : \"value\" } }";
/// Parser parser;
/// Var result = parser.parse(json);
///
/// // use pointers to avoid copying
/// Object::Ptr object = result.extract<Object::Ptr>();
/// Var test = object->get("test"); // holds { "property" : "value" }
/// Object::Ptr subObject = test.extract<Object::Ptr>();
/// test = subObject->get("property");
/// std::string val = test.toString(); // val holds "value"
///
/// // copy/convert to Poco::DynamicStruct
/// Poco::DynamicStruct ds = *object;
/// val = ds["test"]["property"]; // val holds "value"
///
{
public:
typedef SharedPtr<Object> Ptr;
typedef SharedPtr<Object> Ptr;
typedef std::map<std::string, Dynamic::Var> ValueMap;
typedef ValueMap::value_type ValueType;
typedef ValueMap::iterator Iterator;
typedef ValueMap::const_iterator ConstIterator;
Object(bool preserveInsertionOrder = false);
/// Default constructor. If preserveInsertionOrder, object
@ -68,10 +92,31 @@ public:
/// will be sorted by keys.
Object(const Object& copy);
/// Copy constructor
/// Copy constructor. Struct is not copied to keep the operation as
/// efficient as possible (when needed, it will be generated upon request).
virtual ~Object();
/// Destructor
/// Destroys Object.
Iterator begin()
{
return _values.begin();
}
ConstIterator begin() const
{
return _values.begin();
}
Iterator end()
{
return _values.end();
}
ConstIterator end() const
{
return _values.end();
}
Dynamic::Var get(const std::string& key) const;
/// Retrieves a property. An empty value is
@ -108,12 +153,18 @@ public:
bool isArray(const std::string& key) const;
/// Returns true when the given property contains an array
bool isArray(ConstIterator& it) const;
/// Returns true when the given property contains an array
bool isNull(const std::string& key) const;
/// Returns true when the given property contains a null value
bool isObject(const std::string& key) const;
/// Returns true when the given property contains an object
bool isObject(ConstIterator& it) const;
/// Returns true when the given property contains an object
template<typename T>
T optValue(const std::string& key, const T& def) const
/// Returns the value of a property when the property exists
@ -149,8 +200,13 @@ public:
void remove(const std::string& key);
/// Removes the property with the given key
private:
static Poco::DynamicStruct makeStruct(const Object::Ptr& obj);
/// Utility function for creation of struct.
operator const Poco::DynamicStruct& () const;
/// Cast operator to Poco::DynamiStruct.
private:
template <typename C>
void doStringify(const C& container, std::ostream& out, unsigned int indent, int step) const
{
@ -182,17 +238,18 @@ private:
out << '}';
}
typedef std::map<std::string, Dynamic::Var> ValueMap;
typedef std::deque<Dynamic::Var*> KeyPtrList;
typedef std::deque<Dynamic::Var*> KeyPtrList;
typedef Poco::DynamicStruct::Ptr StructPtr;
const std::string& getKey(ValueMap::const_iterator& it) const;
const Dynamic::Var& getValue(ValueMap::const_iterator& it) const;
const std::string& getKey(KeyPtrList::const_iterator& it) const;
const Dynamic::Var& getValue(KeyPtrList::const_iterator& it) const;
ValueMap _values;
KeyPtrList _keys;
bool _preserveInsOrder;
ValueMap _values;
KeyPtrList _keys;
bool _preserveInsOrder;
mutable StructPtr _pStruct;
};
@ -206,6 +263,12 @@ inline bool Object::has(const std::string& key) const
inline bool Object::isArray(const std::string& key) const
{
ValueMap::const_iterator it = _values.find(key);
return isArray(it);
}
inline bool Object::isArray(ConstIterator& it) const
{
return it != _values.end() && it->second.type() == typeid(Array::Ptr);
}
@ -220,6 +283,12 @@ inline bool Object::isNull(const std::string& key) const
inline bool Object::isObject(const std::string& key) const
{
ValueMap::const_iterator it = _values.find(key);
return isObject(it);
}
inline bool Object::isObject(ConstIterator& it) const
{
return it != _values.end() && it->second.type() == typeid(Object::Ptr);
}

View File

@ -60,6 +60,9 @@ public:
virtual ~ParseHandler();
/// Destroys the ParseHandler.
virtual void reset();
/// Resets the handler state.
void startObject();
/// Handles a '{'; a new object is started.
@ -75,7 +78,7 @@ public:
void key(const std::string& k);
/// A key is read
Dynamic::Var result() const;
Dynamic::Var asVar() const;
/// Returns the result of the parser (an object or an array).
virtual void value(int v);
@ -117,7 +120,7 @@ private:
};
inline Dynamic::Var ParseHandler::result() const
inline Dynamic::Var ParseHandler::asVar() const
{
return _result;
}
@ -174,6 +177,10 @@ inline void ParseHandler::null()
}
typedef ParseHandler ParseHandler;
//@ deprecated
}} // namespace Poco::JSON

View File

@ -35,6 +35,29 @@
// DEALINGS IN THE SOFTWARE.
//
/*
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef JSON_JSONParser_INCLUDED
#define JSON_JSONParser_INCLUDED
@ -46,8 +69,6 @@
#include "Poco/JSON/ParseHandler.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/StreamTokenizer.h"
#include <istream>
#include <sstream>
namespace Poco {
@ -58,7 +79,22 @@ class Source;
class JSON_API Parser
/// A class for passing JSON strings or streams.
/// A RFC 4627 compatible class for parsing JSON strings or streams.
///
/// See http://www.ietf.org/rfc/rfc4627.txt for specification.
///
/// Usage example:
///
/// std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }";
/// Parser parser;
/// Var result = parser.parse(json);
/// // ... use result
/// parser.reset();
/// std::ostringstream ostr;
/// PrintHandler::Ptr pHandler = new PrintHandler(ostr);
/// parser.setHandler(pHandler);
/// parser.parse(json); // ostr.str() == json
///
{
public:
@ -170,26 +206,20 @@ public:
enum JSONType
{
JSON_T_NONE = 0,
JSON_T_ARRAY_BEGIN,
JSON_T_ARRAY_END,
JSON_T_OBJECT_BEGIN,
JSON_T_OBJECT_END,
JSON_T_INTEGER,
JSON_T_FLOAT,
JSON_T_NULL,
JSON_T_TRUE,
JSON_T_FALSE,
JSON_T_STRING,
JSON_T_KEY,
JSON_T_VALUE_SEPARATOR,
JSON_T_MAX
};
static const std::size_t PARSE_BUFFER_SIZE = 3500;
static const std::size_t PARSER_STACK_SIZE = 128;
static const int UNLIMITED_DEPTH = -1;
static const std::size_t JSON_PARSE_BUFFER_SIZE = 4096;
static const std::size_t JSON_PARSER_STACK_SIZE = 128;
static const int JSON_UNLIMITED_DEPTH = -1;
Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = PARSE_BUFFER_SIZE);
Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
/// Constructor.
virtual ~Parser();
@ -230,10 +260,16 @@ public:
const Handler::Ptr& getHandler();
/// Returns the handler.
Dynamic::Var result() const;
Dynamic::Var asVar() const;
/// Returns the result of parsing;
Dynamic::Var result() const;
/// Returns the result of parsing as Dynamic::Var;
private:
Parser(const Parser&);
Parser& operator = (const Parser&);
typedef Poco::Buffer<char> BufType;
bool push(int mode);
@ -265,7 +301,7 @@ private:
bool parseChar(int nextChar, Source& feeder);
/// Called for each character (or partial character) in JSON string.
/// It accepts UTF-8, UTF-16, or UTF-32. If it the character is accepted,
/// It accepts UTF-8, UTF-16, or UTF-32. If the character is accepted,
/// it returns true, otherwise false.
bool done();
@ -298,9 +334,9 @@ private:
};
inline void Parser::setAllowComments(bool sw)
inline void Parser::setAllowComments(bool comments)
{
_allowComments = sw;
_allowComments = comments;
}
@ -310,9 +346,9 @@ inline bool Parser::getAllowComments() const
}
inline void Parser::setAllowNullByte(bool sw)
inline void Parser::setAllowNullByte(bool nullByte)
{
_allowNullByte = sw;
_allowNullByte = nullByte;
}
@ -348,7 +384,13 @@ inline const Handler::Ptr& Parser::getHandler()
inline Dynamic::Var Parser::result() const
{
return _pHandler->result();
return _pHandler->asVar();
}
inline Dynamic::Var Parser::asVar() const
{
return _pHandler->asVar();
}

View File

@ -68,6 +68,9 @@ public:
~PrintHandler();
/// Destroys the PrintHandler.
void reset();
/// Resets the handler state.
void startObject();
/// The parser has read a '{'; a new object is started.
/// If indent is greater than zero, a newline will be apended.

View File

@ -116,10 +116,22 @@ bool Array::isNull(unsigned int index) const
bool Array::isObject(unsigned int index) const
{
Var value = get(index);
return isObject(value);
}
bool Array::isObject(const Dynamic::Var& value) const
{
return value.type() == typeid(Object::Ptr);
}
bool Array::isObject(ConstIterator& it) const
{
return it!= end() && isObject(*it);
}
void Array::stringify(std::ostream& out, unsigned int indent, int step) const
{
if (step == -1) step = indent;
@ -152,4 +164,62 @@ void Array::stringify(std::ostream& out, unsigned int indent, int step) const
}
Array::operator const Poco::Dynamic::Array& () const
{
if (!_pArray)
{
ValueVec::const_iterator it = _values.begin();
ValueVec::const_iterator end = _values.end();
_pArray = new Poco::Dynamic::Array;
int index = 0;
for (; it != end; ++it, ++index)
{
if (isObject(it))
{
_pArray->insert(_pArray->end(), Poco::JSON::Object::makeStruct(getObject(index)));
}
else if (isArray(it))
{
_pArray->insert(_pArray->end(), makeArray(getArray(index)));
}
else
{
_pArray->insert(_pArray->end(), *it);
}
}
}
return *_pArray;
}
Poco::Dynamic::Array Array::makeArray(const JSON::Array::Ptr& arr)
{
Poco::Dynamic::Array vec;
JSON::Array::ConstIterator it = arr->begin();
JSON::Array::ConstIterator end = arr->end();
int index = 0;
for (; it != end; ++it, ++index)
{
if (arr->isObject(it))
{
Object::Ptr pObj = arr->getObject(index);
DynamicStruct str = Poco::JSON::Object::makeStruct(pObj);
vec.insert(vec.end(), str);
}
else if (arr->isArray(it))
{
Array::Ptr pArr = arr->getArray(index);
std::vector<Poco::Dynamic::Var> v = makeArray(pArr);
vec.insert(vec.end(), v);
}
else
vec.insert(vec.end(), *it);
}
return vec;
}
} } // namespace Poco::JSON

View File

@ -52,15 +52,16 @@ Handler::~Handler()
}
void Handler::comma()
{
}
Dynamic::Var Handler::result() const
Dynamic::Var Handler::asVar() const
{
return Dynamic::Var();
}
Poco::DynamicStruct Handler::asStruct() const
{
return Poco::DynamicStruct();
}
} } // namespace Poco::JSON

View File

@ -53,7 +53,8 @@ Object::Object(bool preserveInsertionOrder): _preserveInsOrder(preserveInsertion
Object::Object(const Object& copy) : _values(copy._values),
_keys(copy._keys),
_preserveInsOrder(copy._preserveInsOrder)
_preserveInsOrder(copy._preserveInsOrder),
_pStruct(0)
{
}
@ -65,40 +66,37 @@ Object::~Object()
Var Object::get(const std::string& key) const
{
Var value;
ValueMap::const_iterator it = _values.find(key);
if ( it != _values.end() )
if (it != _values.end())
{
value = it->second;
return it->second;
}
return value;
return Var();
}
Array::Ptr Object::getArray(const std::string& key) const
{
Array::Ptr result;
Var value = get(key);
if ( value.type() == typeid(Array::Ptr) )
ValueMap::const_iterator it = _values.find(key);
if ((it != _values.end()) && (it->second.type() == typeid(Array::Ptr)))
{
result = value.extract<Array::Ptr>();
return it->second.extract<Array::Ptr>();
}
return result;
return 0;
}
Object::Ptr Object::getObject(const std::string& key) const
{
Object::Ptr result;
Var value = get(key);
if ( value.type() == typeid(Object::Ptr) )
ValueMap::const_iterator it = _values.find(key);
if ((it != _values.end()) && (it->second.type() == typeid(Object::Ptr)))
{
result = value.extract<Object::Ptr>();
return it->second.extract<Object::Ptr>();
}
return result;
return 0;
}
@ -152,4 +150,60 @@ void 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;
}
Object::operator const Poco::DynamicStruct& () const
{
if (!_pStruct)
{
ValueMap::const_iterator it = _values.begin();
ValueMap::const_iterator end = _values.end();
_pStruct = new Poco::DynamicStruct;
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;
}
} } // namespace Poco::JSON

View File

@ -56,6 +56,14 @@ ParseHandler::~ParseHandler()
}
void ParseHandler::reset()
{
while (!_stack.empty()) _stack.pop();
_key = "";
_result.empty();
}
void ParseHandler::startObject()
{
Object::Ptr newObj = new Object(_preserveObjectOrder);

View File

@ -39,11 +39,11 @@
#include "Poco/Ascii.h"
#include "Poco/Token.h"
#include "Poco/UTF8Encoding.h"
#undef min
#undef max
#include <limits>
#include <clocale>
#include <istream>
namespace Poco {
@ -206,9 +206,9 @@ Parser::Parser(const Handler::Ptr& pHandler, std::size_t bufSize) :
_escaped(0),
_comment(0),
_utf16HighSurrogate(0),
_depth(UNLIMITED_DEPTH),
_depth(JSON_UNLIMITED_DEPTH),
_top(-1),
_stack(PARSER_STACK_SIZE),
_stack(JSON_PARSER_STACK_SIZE),
_parseBuffer(bufSize),
_parseBufferCount(0),
_decimalPoint('.'),
@ -230,7 +230,6 @@ void Parser::reset()
_beforeCommentState = 0;
_type = JSON_T_NONE;
_escaped = 0;
_comment = 0;
_utf16HighSurrogate = 0;
_top = -1;
_parseBufferCount = 0;
@ -239,6 +238,7 @@ void Parser::reset()
_parseBuffer.clear();
push(MODE_DONE);
clearBuffer();
if (_pHandler) _pHandler->reset();
}
@ -255,7 +255,7 @@ Dynamic::Var Parser::parse(const std::string& json)
if (!done())
throw JSONException("JSON syntax error");
return result();
return asVar();
}
@ -272,7 +272,7 @@ Dynamic::Var Parser::parse(std::istream& in)
if (!done())
throw JSONException("JSON syntax error");
return result();
return asVar();
}

View File

@ -66,6 +66,15 @@ PrintHandler::~PrintHandler()
}
void PrintHandler::reset()
{
_out.flush();
_tab = "";
_array = false;
_value = false;
}
const char* PrintHandler::endLine() const
{
if (!printFlat()) return "\n";
@ -217,4 +226,6 @@ void PrintHandler::arrayValue()
_out << _tab;
}
}
} } // namespace Poco::JSON

View File

@ -52,10 +52,13 @@
#include "Poco/Latin1Encoding.h"
#include "Poco/TextConverter.h"
#include "Poco/Dynamic/Struct.h"
#include <set>
using namespace Poco::JSON;
using namespace Poco::Dynamic;
using Poco::DynamicStruct;
JSONTest::JSONTest(const std::string& name): CppUnit::TestCase("JSON")
@ -101,6 +104,12 @@ void JSONTest::testNullProperty()
assert(object->isNull("test"));
Var test = object->get("test");
assert(test.isEmpty());
DynamicStruct ds = *object;
assert (ds["test"].isEmpty());
const DynamicStruct& rds = *object;
assert (rds["test"].isEmpty());
}
@ -127,6 +136,14 @@ void JSONTest::testTrueProperty()
assert(test.type() == typeid(bool));
bool value = test;
assert(value);
DynamicStruct ds = *object;
assert (!ds["test"].isEmpty());
assert (ds["test"]);
const DynamicStruct& rds = *object;
assert (!rds["test"].isEmpty());
assert (rds["test"]);
}
@ -153,6 +170,14 @@ void JSONTest::testFalseProperty()
assert(test.type() == typeid(bool));
bool value = test;
assert(!value);
DynamicStruct ds = *object;
assert (!ds["test"].isEmpty());
assert (!ds["test"]);
const DynamicStruct& rds = *object;
assert (!rds["test"].isEmpty());
assert (!rds["test"]);
}
@ -179,6 +204,16 @@ void JSONTest::testNumberProperty()
assert(test.isInteger());
int value = test;
assert(value == 1969);
DynamicStruct ds = *object;
assert (!ds["test"].isEmpty());
assert (ds["test"].isNumeric());
assert (ds["test"] == 1969);
const DynamicStruct& rds = *object;
assert (!rds["test"].isEmpty());
assert (rds["test"].isNumeric());
assert (rds["test"] == 1969);
}
@ -203,8 +238,25 @@ void JSONTest::testUnsignedNumberProperty()
Object::Ptr object = result.extract<Object::Ptr>();
Var test = object->get("test");
assert(test.isNumeric());
assert(test.isInteger());
unsigned value = test;
Poco::UInt32 value = test;
assert(value == -1);
DynamicStruct ds = *object;
assert (!ds["test"].isEmpty());
assert (ds["test"].isNumeric());
assert (ds["test"].isInteger());
assert (ds["test"] == 4294967295);
value = ds["test"];
assert(value == -1);
const DynamicStruct& rds = *object;
assert (!rds["test"].isEmpty());
assert (rds["test"].isNumeric());
assert (rds["test"].isInteger());
assert (rds["test"] == 4294967295);
value = rds["test"];
assert(value == -1);
}
@ -229,11 +281,27 @@ void JSONTest::testNumber64Property()
assert(result.type() == typeid(Object::Ptr));
Object::Ptr object = result.extract<Object::Ptr>();
Var test = object->get("test");
Object object = *result.extract<Object::Ptr>();
Var test = object.get("test");
assert(test.isInteger());
Poco::Int64 value = test;
assert(value == -5000000000000000);
DynamicStruct ds = object;
assert (!ds["test"].isEmpty());
assert (ds["test"].isNumeric());
assert (ds["test"].isInteger());
assert (ds["test"] == -5000000000000000);
value = ds["test"];
assert(value == -5000000000000000);
const DynamicStruct& rds = object;
assert (!rds["test"].isEmpty());
assert (rds["test"].isNumeric());
assert (rds["test"].isInteger());
assert (rds["test"] == -5000000000000000);
value = rds["test"];
assert(value == -5000000000000000);
}
@ -261,6 +329,22 @@ void JSONTest::testUnsignedNumber64Property()
assert(test.isInteger());
Poco::UInt64 value = test;
assert(value == -1);
DynamicStruct ds = *object;
assert (!ds["test"].isEmpty());
assert (ds["test"].isNumeric());
assert (ds["test"].isInteger());
assert (ds["test"] == 18446744073709551615);
value = ds["test"];
assert(value == -1);
const DynamicStruct& rds = *object;
assert (!rds["test"].isEmpty());
assert (rds["test"].isNumeric());
assert (rds["test"].isInteger());
assert (rds["test"] == 18446744073709551615);
value = rds["test"];
assert(value == -1);
}
#endif
@ -284,11 +368,27 @@ void JSONTest::testStringProperty()
assert(result.type() == typeid(Object::Ptr));
Object::Ptr object = result.extract<Object::Ptr>();
Var test = object->get("test");
Object object = *result.extract<Object::Ptr>();
Var test = object.get("test");
assert(test.isString());
std::string value = test.convert<std::string>();
assert(value.compare("value") == 0);
DynamicStruct ds = object;
assert (!ds["test"].isEmpty());
assert (ds["test"].isString());
assert (!ds["test"].isInteger());
assert (ds["test"] == "value");
value = ds["test"].toString();
assert(value == "value");
const DynamicStruct& rds = object;
assert (!rds["test"].isEmpty());
assert (rds["test"].isString());
assert (!rds["test"].isInteger());
assert (rds["test"] == "value");
value = rds["test"].toString();
assert(value == "value");
}
@ -312,6 +412,12 @@ void JSONTest::testEmptyObject()
Object::Ptr object = result.extract<Object::Ptr>();
assert(object->size() == 0);
DynamicStruct ds = *object;
assert (ds.size() == 0);
const DynamicStruct& rds = *object;
assert (rds.size() == 0);
}
@ -386,12 +492,65 @@ void JSONTest::testComplexObject()
}
assert(result.type() == typeid(Object::Ptr));
Object::Ptr object = result.extract<Object::Ptr>();
assert(object->size() > 0);
DynamicStruct ds = *object;
assert (ds.size() > 0);
assert (ds["id"] == 1);
assert (ds["jsonrpc"] == 2.0);
assert (ds["result"].isArray());
assert (ds["result"].size() == 1);
assert (ds["result"][0].isStruct());
assert (ds["result"][0]["id"] == 1);
assert (ds["result"][0]["guid"] == "67acfb26-17eb-4a75-bdbd-f0669b7d8f73");
assert (ds["result"][0]["age"] == 40);
assert (ds["result"][0]["name"] == "Angelina Crossman");
assert (ds["result"][0]["gender"] == "female");
assert (ds["result"][0]["company"] == "Raylog");
assert (ds["result"][0]["phone"] == "892-470-2803");
assert (ds["result"][0]["email"] == "angelina@raylog.com");
assert (ds["result"][0]["address"] == "20726, CostaMesa, Horatio Streets");
assert (ds["result"][0]["about"] == "Consectetuer suscipit volutpat eros dolor euismod, "
"et dignissim in feugiat sed, ea tation exerci quis. Consectetuer, "
"dolor dolore ad vero ullamcorper, tincidunt facilisis at in facilisi, "
"iusto illum illum. Autem nibh, sed elit consequat volutpat tation, "
"nisl lorem lorem sed tation, facilisis dolore. Augue odio molestie, "
"dolor zzril nostrud aliquam sed, wisi dolor et ut iusto, ea. Magna "
"ex qui facilisi, hendrerit quis in eros ut, zzril nibh dolore nisl "
"suscipit, vulputate elit ut lobortis exerci, nulla dolore eros at "
"aliquam, ullamcorper vero ad iusto. Adipiscing, nisl eros exerci "
"nisl vel, erat in luptatum in duis, iusto.");
assert (ds["result"][0]["registered"] == "2008-04-09T11:13:17 +05:00");
assert (ds["result"][0]["tags"].isArray());
assert (ds["result"][0]["tags"].size() == 7);
assert (ds["result"][0]["tags"][0] == "ut");
assert (ds["result"][0]["tags"][1] == "accumsan");
assert (ds["result"][0]["tags"][2] == "feugait");
assert (ds["result"][0]["tags"][3] == "ex");
assert (ds["result"][0]["tags"][4] == "odio");
assert (ds["result"][0]["tags"][5] == "consequat");
assert (ds["result"][0]["tags"][6] == "delenit");
assert (ds["result"][0]["friends"][0].isStruct());
assert (ds["result"][0]["friends"][0]["id"] == 1);
assert (ds["result"][0]["friends"][0]["name"] == "Hailey Hardman");
assert (ds["result"][0]["friends"][1]["id"] == 2);
assert (ds["result"][0]["friends"][1]["name"] == "Bailey Oldridge");
assert (ds["result"][0]["friends"][2]["id"] == 3);
assert (ds["result"][0]["friends"][2]["name"] == "Makayla Campbell");
const DynamicStruct& rds = *object;
assert (rds.size() > 0);
}
void JSONTest::testDoubleProperty()
{
std::string json = "{ \"test\" : 123.45 }";
std::string json = "{ \"test\" : 1234.5 }";
Parser parser;
Var result;
@ -411,7 +570,10 @@ void JSONTest::testDoubleProperty()
Var test = object->get("test");
assert(test.isNumeric());
double value = test;
assert(value == 123.45);
assert(value == 1234.5);
DynamicStruct ds = *object;
assert (ds["test"] == 1234.5);
}
@ -491,12 +653,16 @@ void JSONTest::testObjectProperty()
Var test = object->get("test");
assert(test.type() == typeid(Object::Ptr));
object = test.extract<Object::Ptr>();
Object::Ptr subObject = test.extract<Object::Ptr>();
test = object->get("property");
test = subObject->get("property");
assert(test.isString());
std::string value = test.convert<std::string>();
assert(value.compare("value") == 0);
DynamicStruct ds = *object;
assert (ds["test"].isStruct());
assert (ds["test"]["property"] == "value");
}
@ -519,11 +685,23 @@ void JSONTest::testObjectArray()
assert(result.type() == typeid(Object::Ptr));
Object::Ptr object = result.extract<Object::Ptr>();
assert(object->isObject("test"));
object = object->getObject("test");
assert(!object->isObject("test1"));
assert(object->isArray("test1"));
assert(!object->isObject("test2"));
assert(!object->isArray("test2"));
Object::Ptr subObject = object->getObject("test");
assert(!subObject->isObject("test1"));
assert(subObject->isArray("test1"));
assert(!subObject->isObject("test2"));
assert(!subObject->isArray("test2"));
DynamicStruct ds = *object;
assert (ds.size() > 0);
assert (ds.size() == 1);
assert (ds["test"].isStruct());
assert (ds["test"]["test1"].isArray());
assert (ds["test"]["test1"].size() == 3);
assert (ds["test"]["test1"][0] == 1);
assert (ds["test"]["test1"][1] == 2);
assert (ds["test"]["test1"][2] == 3);
assert (ds["test"]["test2"] == 4);
}
@ -543,15 +721,25 @@ void JSONTest::testArrayOfObjects()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
Array::Ptr arr = result.extract<Array::Ptr>();
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Poco::JSON::Array::Ptr arr = result.extract<Poco::JSON::Array::Ptr>();
Object::Ptr object = arr->getObject(0);
assert (object->getValue<int>("test") == 0);
object = arr->getObject(1);
arr = object->getArray("test1");
result = arr->get(0);
Object::Ptr subObject = arr->getObject(1);
Poco::JSON::Array::Ptr subArr = subObject->getArray("test1");
result = subArr->get(0);
assert (result == 1);
Poco::Dynamic::Array da = *arr;
assert (da.size() == 2);
assert (da[0].isStruct());
assert (da[0]["test"] == 0);
assert (da[1].isStruct());
assert (da[1]["test1"].isArray());
assert (da[1]["test1"][0] == 1);
assert (da[1]["test1"][1] == 2);
assert (da[1]["test1"][2] == 3);
assert (da[1]["test2"] == 4);
}
@ -571,10 +759,13 @@ void JSONTest::testEmptyArray()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
assert(array->size() == 0);
Poco::Dynamic::Array da = *array;
assert (da.size() == 0);
}
@ -594,10 +785,16 @@ void JSONTest::testNestedArray()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
assert(array->size() == 1);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0].size() == 1);
assert (da[0][0].size() == 1);
assert (da[0][0][0].size() == 0);
}
@ -617,12 +814,16 @@ void JSONTest::testNullElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
assert(array->isNull(0));
Var test = array->get(0);
assert(test.isEmpty());
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0].isEmpty());
}
@ -642,13 +843,17 @@ void JSONTest::testTrueElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Var test = array->get(0);
assert(test.type() == typeid(bool));
bool value = test;
assert(value);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0]);
}
@ -668,13 +873,17 @@ void JSONTest::testFalseElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Var test = array->get(0);
assert(test.type() == typeid(bool));
bool value = test;
assert(!value);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (!da[0]);
}
@ -694,13 +903,17 @@ void JSONTest::testNumberElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Var test = array->get(0);
assert(test.isInteger());
int value = test;
assert(value == 1969);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0] == 1969);
}
@ -720,13 +933,17 @@ void JSONTest::testStringElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Var test = array->get(0);
assert(test.isString());
std::string value = test.convert<std::string>();
assert(value.compare("value") == 0);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0] == "value");
}
@ -746,17 +963,22 @@ void JSONTest::testEmptyObjectElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Object::Ptr object = array->getObject(0);
assert(object->size() == 0);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0].isStruct());
assert (da[0].size() == 0);
}
void JSONTest::testDoubleElement()
{
std::string json = "[ 123.45 ]";
std::string json = "[ 1234.5 ]";
Parser parser;
Var result;
@ -770,13 +992,17 @@ void JSONTest::testDoubleElement()
assert(false);
}
assert(result.type() == typeid(Array::Ptr));
assert(result.type() == typeid(Poco::JSON::Array::Ptr));
Array::Ptr array = result.extract<Array::Ptr>();
Poco::JSON::Array::Ptr array = result.extract<Poco::JSON::Array::Ptr>();
Var test = array->get(0);
assert(test.isNumeric());
double value = test;
assert(value == 123.45);
assert(value == 1234.5);
Poco::Dynamic::Array da = *array;
assert (da.size() == 1);
assert (da[0] == 1234.5);
}
@ -826,6 +1052,48 @@ void JSONTest::testQuery()
std::string firstChild = query.findValue("children[0]", "");
assert(firstChild.compare("Jonas") == 0);
Poco::DynamicStruct ds = *result.extract<Object::Ptr>();
assert (ds["name"] == "Franky");
assert (ds["children"].size() == 2);
assert (ds["children"][0] == "Jonas");
assert (ds["children"][1] == "Ellen");
}
void JSONTest::testComment()
{
std::string json = "{ \"name\" : \"Franky\" /* father */, \"children\" : [ \"Jonas\" /* son */ , \"Ellen\" /* daughter */ ] }";
Parser parser;
Var result;
try
{
parser.parse(json);
fail ("must fail");
}
catch(Poco::SyntaxException&)
{
}
parser.reset();
parser.setAllowComments(true);
try
{
result = parser.parse(json);
}
catch(JSONException& jsone)
{
std::cout << jsone.message() << std::endl;
assert(false);
}
assert(result.type() == typeid(Object::Ptr));
Query query(result);
std::string firstChild = query.findValue("children[0]", "");
assert(firstChild.compare("Jonas") == 0);
}
@ -1127,6 +1395,26 @@ void JSONTest::testStringifyPreserveOrder()
" }\n"
" }\n"
"}");
Poco::DynamicStruct ds = *result.extract<Object::Ptr>();
assert (ds["Simpsons"].isStruct());
assert (ds["Simpsons"]["husband"].isStruct());
assert (ds["Simpsons"]["husband"]["name"] == "Homer");
assert (ds["Simpsons"]["husband"]["age"] == 38);
assert (ds["Simpsons"]["wife"].isStruct());
assert (ds["Simpsons"]["wife"]["name"] == "Marge");
assert (ds["Simpsons"]["wife"]["age"] == 36);
assert (ds["Simpsons"]["children"].isArray());
assert (ds["Simpsons"]["children"][0] == "Bart");
assert (ds["Simpsons"]["children"][1] == "Lisa");
assert (ds["Simpsons"]["children"][2] == "Maggie");
assert (ds["Simpsons"]["address"].isStruct());
assert (ds["Simpsons"]["address"]["number"] == 742);
assert (ds["Simpsons"]["address"]["street"] == "Evergreen Terrace");
assert (ds["Simpsons"]["address"]["town"] == "Springfield");
}
@ -1155,7 +1443,7 @@ void JSONTest::testValidJanssonFiles()
try
{
parser.parse(fis);
result = parser.result();
result = parser.asVar();
std::cout << "Ok!" << std::endl;
}
catch(JSONException& jsone)
@ -1202,7 +1490,7 @@ void JSONTest::testInvalidJanssonFiles()
try
{
parser.parse(fis);
result = parser.result();
result = parser.asVar();
// We shouldn't get here.
std::cout << "We didn't get an exception. This is the result: " << result.convert<std::string>() << std::endl;
fail(result.convert<std::string>());
@ -1245,7 +1533,7 @@ void JSONTest::testInvalidUnicodeJanssonFiles()
try
{
parser.parse(fis);
result = parser.result();
result = parser.asVar();
// We shouldn't get here.
std::cout << "We didn't get an exception. This is the result: " << result.convert<std::string>() << std::endl;
fail(result.convert<std::string>());
@ -1291,7 +1579,7 @@ void JSONTest::testUnicode()
try
{
parser.parse(json);
result = parser.result();
result = parser.asVar();
}
catch(JSONException& jsone)
{
@ -1374,6 +1662,7 @@ CppUnit::Test* JSONTest::suite()
CppUnit_addTest(pSuite, JSONTest, testDoubleElement);
CppUnit_addTest(pSuite, JSONTest, testOptValue);
CppUnit_addTest(pSuite, JSONTest, testQuery);
CppUnit_addTest(pSuite, JSONTest, testComment);
CppUnit_addTest(pSuite, JSONTest, testPrintHandler);
CppUnit_addTest(pSuite, JSONTest, testStringify);
CppUnit_addTest(pSuite, JSONTest, testStringifyPreserveOrder);

View File

@ -75,6 +75,7 @@ public:
void testDoubleElement();
void testOptValue();
void testQuery();
void testComment();
void testPrintHandler();
void testStringify();
void testStringifyPreserveOrder();

View File

@ -189,3 +189,60 @@ public domain (http://www.sqlite.org/copyright.html).
Anyone is free to copy, modify, publish, use, compile, sell, or distribute the
original SQLite code, either in source code form or as a compiled binary,
for any purpose, commercial or non-commercial, and by any means.
----
!!!double-conversion
Copyright 2010 the V8 project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----
!!!JSON_parser
Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -227,6 +227,29 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre></p>
<h3>JSON_parser</h3>
<p><pre>Copyright (c) 2005 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</pre></p>
</body>
</html>