Dynamic::Var SOO

Dynamic::Var  small object optimization and some refactoring
This commit is contained in:
aleks-f 2013-02-05 22:12:21 -06:00
parent 54a92c59e5
commit 21da0129b6
16 changed files with 401 additions and 208 deletions

3
.gitignore vendored
View File

@ -100,3 +100,6 @@ lib/
lib64/
pocomsg.h
# Temporary files #
###################
*.bak

View File

@ -225,9 +225,9 @@ public:
val = DateTimeFormatter::format(dt, "%Y/%m/%d");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::Date& value() const

View File

@ -272,9 +272,9 @@ public:
val.assign(_val.begin(), _val.end());
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::BLOB& value() const
@ -310,9 +310,9 @@ public:
val.assign(_val.begin(), _val.end());
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::CLOB& value() const

View File

@ -229,9 +229,9 @@ public:
val = DateTimeFormatter::format(dt, "%H:%M:%S");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::Time& value() const

View File

@ -48,6 +48,68 @@
namespace Poco {
namespace Dynamic {
class Var;
class VarHolder;
template <class> class VarHolderImpl;
}
template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
union Placeholder
/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
/// object optimization).
///
/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
/// it will be placement-new-allocated into the local buffer
/// (i.e. there will be no heap-allocation). The local buffer size is one byte
/// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
/// where the object was allocated (0 => heap, 1 => local).
{
public:
static const unsigned int SIZE = SizeV;
Placeholder ()
{
erase();
}
void erase()
{
std::memset(holder, 0, sizeof(Placeholder));
}
bool isLocal() const
{
return holder[SIZE] != 0;
}
void setLocal(bool local) const
{
holder[SIZE] = local ? 1 : 0;
}
PlaceholderT* content() const
{
if(isLocal())
return reinterpret_cast<PlaceholderT*>(holder);
else
return pHolder;
}
private:
PlaceholderT* pHolder;
mutable unsigned char holder[SIZE + 1];
friend class Any;
friend class Dynamic::Var;
friend class Dynamic::VarHolder;
template <class> friend class VarHolderImpl;
};
class Any
/// An Any class represents a general type and is capable of storing any type, supporting type-safe extraction
/// of the internally stored data.
@ -58,13 +120,10 @@ class Any
/// Modified for small object optimization support (optionally supported through conditional compilation)
/// by Alex Fabijanic.
{
public:
#ifndef POCO_NO_SOO
union PH;
public:
Any()
/// Creates an empty any type.
{
@ -75,8 +134,8 @@ public:
/// Creates an any which stores the init parameter inside.
///
/// Example:
/// Any a(13);
/// Any a(string("12345"));
/// Any a(13);
/// Any a(string("12345"));
{
construct(value);
}
@ -89,13 +148,13 @@ public:
}
~Any()
/// Destructor. If Any is locally held, calls Placeholder destructor;
/// Destructor. If Any is locally held, calls ValueHolder destructor;
/// otherwise, deletes the placeholder from the heap.
{
if(!empty())
{
if(_placeholder.isLocal())
content()->~Placeholder();
if(_valueHolder.isLocal())
content()->~ValueHolder();
else
delete content();
}
@ -110,14 +169,14 @@ public:
{
if (this == &other) return *this;
if (!_placeholder.isLocal() && !other._placeholder.isLocal())
if (!_valueHolder.isLocal() && !other._valueHolder.isLocal())
{
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
std::swap(_valueHolder.pHolder, other._valueHolder.pHolder);
}
else
{
Any tmp(*this);
if (_placeholder.isLocal()) this->~Any();
if (_valueHolder.isLocal()) this->~Any();
construct(other);
other = tmp;
}
@ -143,7 +202,7 @@ public:
if ((this != &rhs) && !rhs.empty())
construct(rhs);
else if ((this != &rhs) && rhs.empty())
_placeholder.erase();
_valueHolder.erase();
return *this;
}
@ -152,7 +211,7 @@ public:
/// Returns true if the Any is empty.
{
char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
return 0 == std::memcmp(_placeholder.holder, buf, POCO_SMALL_OBJECT_SIZE);
return 0 == std::memcmp(_valueHolder.holder, buf, _valueHolder.SIZE);
}
const std::type_info & type() const
@ -166,20 +225,20 @@ public:
private:
class Placeholder
class ValueHolder
{
public:
virtual ~Placeholder()
virtual ~ValueHolder()
{
}
virtual const std::type_info & type() const = 0;
virtual void clone(Any::PH*) const = 0;
virtual void clone(Placeholder<ValueHolder>*) const = 0;
};
template<typename ValueType>
class Holder : public Placeholder
class Holder : public ValueHolder
{
public:
Holder(const ValueType & value) : _held(value)
@ -191,11 +250,11 @@ private:
return typeid(ValueType);
}
virtual void clone(Any::PH* pPlaceholder) const
virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
{
if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
if ((sizeof(Holder<ValueType>) <= pPlaceholder->SIZE))
{
new ((Placeholder*) pPlaceholder->holder) Holder(_held);
new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
pPlaceholder->setLocal(true);
}
else
@ -211,78 +270,40 @@ private:
Holder & operator = (const Holder &);
};
Placeholder* content() const
ValueHolder* content() const
{
return _placeholder.content();
return _valueHolder.content();
}
template<typename ValueType>
void construct(const ValueType& value)
{
if (sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE)
if (sizeof(Holder<ValueType>) <= _valueHolder.SIZE)
{
new (reinterpret_cast<Placeholder*>(_placeholder.holder)) Holder<ValueType>(value);
_placeholder.setLocal(true);
new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
_valueHolder.setLocal(true);
}
else
{
_placeholder.pHolder = new Holder<ValueType>(value);
_placeholder.setLocal(false);
_valueHolder.pHolder = new Holder<ValueType>(value);
_valueHolder.setLocal(false);
}
}
void construct(const Any& other)
{
if(!other.empty())
other.content()->clone(&_placeholder);
other.content()->clone(&_valueHolder);
else
_placeholder.erase();
_valueHolder.erase();
}
union PH
/// Placeholder union. If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE
/// bytes of storage, it will be placement-new-allocated into the local buffer
/// (i.e. there will be no heap-allocation. The local buffer size is one byte
/// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
/// where the object was allocated (0 => heap, 1 => local).
{
PH ()
{
erase();
}
void erase()
{
std::memset(holder, 0, sizeof(PH));
}
bool isLocal() const
{
return holder[POCO_SMALL_OBJECT_SIZE] != 0;
}
void setLocal(bool local) const
{
holder[POCO_SMALL_OBJECT_SIZE] = local ? 1 : 0;
}
Placeholder* content() const
{
if(isLocal())
return reinterpret_cast<Placeholder*>(holder);
else
return pHolder;
}
Placeholder* pHolder;
mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1];
} _placeholder;
Placeholder<ValueHolder> _valueHolder;
#else // if POCO_NO_SOO
public:
Any(): _pHolder(0)
/// Creates an empty any type.
{
@ -352,19 +373,19 @@ public:
}
private:
class Placeholder
class ValueHolder
{
public:
virtual ~Placeholder()
virtual ~ValueHolder()
{
}
virtual const std::type_info& type() const = 0;
virtual Placeholder* clone() const = 0;
virtual ValueHolder* clone() const = 0;
};
template <typename ValueType>
class Holder: public Placeholder
class Holder: public ValueHolder
{
public:
Holder(const ValueType& value):
@ -377,7 +398,7 @@ private:
return typeid(ValueType);
}
virtual Placeholder* clone() const
virtual ValueHolder* clone() const
{
return new Holder(_held);
}
@ -388,13 +409,13 @@ private:
Holder & operator=(const Holder &);
};
Placeholder* content() const
ValueHolder* content() const
{
return _pHolder;
}
private:
Placeholder* _pHolder;
ValueHolder* _pHolder;
#endif // POCO_NO_SOO

View File

@ -93,6 +93,16 @@
// (see Poco/Types.h for default values).
// #define POCO_NO_SOO
// Small object size in bytes. Where applicable (e.g.
// SmallObjectAllocator<char*> specialization, Any, Var, etc)
// objects longer than this value will be alocated on the heap.
// See Poco/SmallObjectAllocator.h for usage of this value.
#if !defined(POCO_SMALL_OBJECT_SIZE)
#define POCO_SMALL_OBJECT_SIZE 32
#endif
// Following are options to remove certain features
// to reduce library/executable size for smaller
// embedded platforms. By enabling these options,

View File

@ -229,9 +229,9 @@ public:
throw BadCastException("Pair -> Poco::Timestamp");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Pair<std::string>& value() const
@ -378,9 +378,9 @@ public:
throw BadCastException("Pair -> Poco::Timestamp");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Pair<int>& value() const

View File

@ -325,9 +325,9 @@ public:
throw BadCastException("Struct -> Poco::Timestamp");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Struct<std::string>& value() const
@ -496,9 +496,9 @@ public:
throw BadCastException("Struct -> Poco::Timestamp");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Struct<int>& value() const

View File

@ -53,6 +53,7 @@ namespace Dynamic {
template <typename T>
class Struct;
class Foundation_API Var
/// Var allows to store data of different types and to convert between these types transparently.
/// Var puts forth the best effort to provide intuitive and reasonable conversion semantics and prevent
@ -88,7 +89,7 @@ class Foundation_API Var
/// '+', '+=', '-', '-=', '*', '*=' , '/' and '/='
///
/// - for integral values, following operations are supported:
/// prefix and postfix increment (++) and decement (--)
/// prefix and postfix increment (++) and decrement (--)
///
/// - for all other types, InvalidArgumentException is thrown upon attempt of an arithmetic operation
///
@ -100,11 +101,15 @@ public:
/// Creates an empty Var.
template <typename T>
Var(const T& val):
_pHolder(new VarHolderImpl<T>(val))
Var(const T& val)
/// Creates the Var from the given value.
#ifdef POCO_NO_SOO
:_pHolder(new VarHolderImpl<T>(val)) { }
#else
{
construct(val);
}
#endif
Var(const char* pVal);
// Convenience constructor for const char* which gets mapped to a std::string internally, i.e. pVal is deep-copied.
@ -133,10 +138,12 @@ public:
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
{
if (!_pHolder)
VarHolder* pHolder = content();
if (!pHolder)
throw InvalidAccessException("Can not convert empty value.");
_pHolder->convert(val);
pHolder->convert(val);
}
template <typename T>
@ -153,13 +160,15 @@ public:
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
{
if (!_pHolder)
VarHolder* pHolder = content();
if (!pHolder)
throw InvalidAccessException("Can not convert empty value.");
if (typeid(T) == _pHolder->type()) return extract<T>();
if (typeid(T) == pHolder->type()) return extract<T>();
T result;
_pHolder->convert(result);
pHolder->convert(result);
return result;
}
@ -177,15 +186,17 @@ public:
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
{
if (!_pHolder)
VarHolder* pHolder = content();
if (!pHolder)
throw InvalidAccessException("Can not convert empty value.");
if (typeid(T) == _pHolder->type())
if (typeid(T) == pHolder->type())
return extract<T>();
else
{
T result;
_pHolder->convert(result);
pHolder->convert(result);
return result;
}
}
@ -199,16 +210,18 @@ public:
/// is thrown.
/// Throws InvalidAccessException if Var is empty.
{
if (_pHolder && _pHolder->type() == typeid(T))
VarHolder* pHolder = content();
if (pHolder && pHolder->type() == typeid(T))
{
VarHolderImpl<T>* pHolderImpl = static_cast<VarHolderImpl<T>*>(_pHolder);
VarHolderImpl<T>* pHolderImpl = static_cast<VarHolderImpl<T>*>(pHolder);
return pHolderImpl->value();
}
else if (!_pHolder)
else if (!pHolder)
throw InvalidAccessException("Can not extract empty value.");
else
throw BadCastException(format("Can not convert %s to %s.",
_pHolder->type().name(),
pHolder->type().name(),
typeid(T).name()));
}
@ -216,8 +229,12 @@ public:
Var& operator = (const T& other)
/// Assignment operator for assigning POD to Var
{
#ifdef POCO_NO_SOO
Var tmp(other);
swap(tmp);
#else
construct(other);
#endif
return *this;
}
@ -536,9 +553,11 @@ private:
template <typename T, typename E>
VarHolderImpl<T>* holderImpl(const std::string errorMessage = "") const
{
if (_pHolder && _pHolder->type() == typeid(T))
return static_cast<VarHolderImpl<T>*>(_pHolder);
else if (!_pHolder)
VarHolder* pHolder = content();
if (pHolder && pHolder->type() == typeid(T))
return static_cast<VarHolderImpl<T>*>(pHolder);
else if (!pHolder)
throw InvalidAccessException("Can not access empty value.");
else
throw E(errorMessage);
@ -546,7 +565,64 @@ private:
Var& structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const;
#ifdef POCO_NO_SOO
VarHolder* content() const
{
return _pHolder;
}
VarHolder* _pHolder;
#else
VarHolder* content() const
{
return _placeholder.content();
}
template<typename ValueType>
void construct(const ValueType& value)
{
if (sizeof(VarHolderImpl<ValueType>) <= _placeholder.SIZE)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
_placeholder.setLocal(true);
}
else
{
_placeholder.pHolder = new VarHolderImpl<ValueType>(value);
_placeholder.setLocal(false);
}
}
void construct(const char* value)
{
std::string val(value);
if (sizeof(VarHolderImpl<std::string>) <= _placeholder.SIZE)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
_placeholder.setLocal(true);
}
else
{
_placeholder.pHolder = new VarHolderImpl<std::string>(val);
_placeholder.setLocal(false);
}
}
void construct(const Var& other)
{
if(!other.isEmpty())
other.content()->clone(&_placeholder);
else
_placeholder.erase();
}
Placeholder<VarHolder> _placeholder;
#endif // POCO_NO_SOO
};
@ -559,15 +635,36 @@ private:
/// Var members
///
inline void Var::swap(Var& ptr)
inline void Var::swap(Var& other)
{
std::swap(_pHolder, ptr._pHolder);
#ifdef POCO_NO_SOO
std::swap(_pHolder, other._pHolder);
#else
if (this == &other) return;
if (!_placeholder.isLocal() && !other._placeholder.isLocal())
{
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
}
else
{
Var tmp(*this);
if (_placeholder.isLocal()) this->~Var();
construct(other);
other = tmp;
}
#endif
}
inline const std::type_info& Var::type() const
{
return _pHolder ? _pHolder->type() : typeid(void);
VarHolder* pHolder = content();
return pHolder ? pHolder->type() : typeid(void);
}
@ -603,49 +700,56 @@ inline bool Var::operator ! () const
inline bool Var::isEmpty() const
{
return 0 == _pHolder;
return 0 == content();
}
inline bool Var::isArray() const
{
return _pHolder ? _pHolder->isArray() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isArray() : false;
}
inline bool Var::isStruct() const
{
return _pHolder ? _pHolder->isStruct() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isStruct() : false;
}
inline bool Var::isInteger() const
{
return _pHolder ? _pHolder->isInteger() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isInteger() : false;
}
inline bool Var::isSigned() const
{
return _pHolder ? _pHolder->isSigned() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isSigned() : false;
}
inline bool Var::isNumeric() const
{
return _pHolder ? _pHolder->isNumeric() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isNumeric() : false;
}
inline bool Var::isString() const
{
return _pHolder ? _pHolder->isString() : false;
VarHolder* pHolder = content();
return pHolder ? pHolder->isString() : false;
}
///
/// Var non-member functions
///
inline const Var operator + (const char* other, const Var& da)
/// Addition operator for adding Var to const char*
{

View File

@ -50,6 +50,7 @@
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeParser.h"
#include "Poco/String.h"
#include "Poco/Any.h"
#include "Poco/Exception.h"
#include <vector>
#include <typeinfo>
@ -68,6 +69,7 @@ class Var;
bool Foundation_API isJSONString(const Var& any);
/// Returns true for values that should be JSON-formatted as string.
void Foundation_API appendJSONString(std::string& val, const Var& any);
/// Converts the any to a JSON value and adds it to val
@ -92,13 +94,17 @@ public:
virtual ~VarHolder();
/// Destroys the VarHolder.
virtual VarHolder* clone() const;
/// Throws NotImplementedException. Implementation should
virtual VarHolder* clone(Placeholder<VarHolder>* pHolder = 0) const = 0;
/// Implementation must implement this function to
/// deep-copy the VarHolder.
virtual const std::type_info& type() const;
/// Throws NotImplementedException. Implementation should
/// return the type information for the stored content.
/// If small object optimization is enabled (i.e. if
/// POCO_NO_SOO is not defined), VarHolder will be
/// instantiated in-place if it's size is smaller
/// than POCO_SMALL_OBJECT_SIZE.
virtual const std::type_info& type() const = 0;
/// Implementation must return the type information
/// (typeid) for the stored content.
virtual void convert(Int8& val) const;
/// Throws BadCastException. Must be overriden in a type
@ -145,12 +151,15 @@ public:
/// specialization in order to suport the conversion.
#ifndef POCO_LONG_IS_64_BIT
void convert(long& val) const;
/// Calls convert(Int32).
void convert(unsigned long& val) const;
/// Calls convert(UInt32).
#endif
virtual void convert(bool& val) const;
/// Throws BadCastException. Must be overriden in a type
/// specialization in order to suport the conversion.
@ -199,6 +208,35 @@ protected:
VarHolder();
/// Creates the VarHolder.
template <typename T>
VarHolder* cloneHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
/// Instantiates value holder wrapper. If size of the wrapper is
/// larger than POCO_SMALL_OBJECT_SIZE, holder is instantiated on
/// the heap, otherwise it is instantiated in-place (in the
/// pre-allocated buffer inside the holder).
///
/// Called from clone() member function of the implementation when
/// smal object optimization is enabled.
{
#ifdef POCO_NO_SOO
return new VarHolderImpl<T>(val);
#else
poco_check_ptr (pVarHolder);
if ((sizeof(VarHolderImpl<T>) <= pVarHolder->SIZE))
{
new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
pVarHolder->setLocal(true);
return (VarHolder*) pVarHolder->holder;
}
else
{
pVarHolder->pHolder = new VarHolderImpl<T>(val);
pVarHolder->setLocal(false);
return pVarHolder->pHolder;
}
#endif
}
template <typename F, typename T>
void convertToSmaller(const F& from, T& to) const
/// This function is meant to convert signed numeric values from
@ -338,16 +376,6 @@ private:
// inlines
//
inline VarHolder* VarHolder::clone() const
{
throw NotImplementedException("Not implemented: VarHolder::clone()");
}
inline const std::type_info& VarHolder::type() const
{
throw NotImplementedException("Not implemented: VarHolder::type()");
}
inline void VarHolder::convert(Int8& /*val*/) const
{
@ -414,8 +442,8 @@ inline void VarHolder::convert(Timestamp& /*val*/) const
throw BadCastException("Can not convert to Timestamp");
}
#ifndef POCO_LONG_IS_64_BIT
inline void VarHolder::convert(long& val) const
{
Int32 tmp;
@ -430,8 +458,8 @@ inline void VarHolder::convert(unsigned long& val) const
convert(tmp);
val = tmp;
}
#endif
#endif
inline void VarHolder::convert(bool& /*val*/) const
{
@ -533,9 +561,9 @@ public:
return typeid(T);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const T& value() const
@ -634,9 +662,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Int8& value() const
@ -767,9 +795,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Int16& value() const
@ -900,9 +928,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Int32& value() const
@ -1048,9 +1076,9 @@ public:
val = Timestamp(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Int64& value() const
@ -1181,9 +1209,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const UInt8& value() const
@ -1314,9 +1342,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const UInt16& value() const
@ -1447,9 +1475,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const UInt32& value() const
@ -1601,9 +1629,9 @@ public:
val = Timestamp(tmp);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const UInt64& value() const
@ -1732,9 +1760,9 @@ public:
val = (_val ? "true" : "false");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const bool& value() const
@ -1866,9 +1894,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const float& value() const
@ -2006,9 +2034,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const double& value() const
@ -2137,9 +2165,9 @@ public:
val = std::string(1, _val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const char& value() const
@ -2316,9 +2344,9 @@ public:
ts = tmp.timestamp();
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const std::string& value() const
@ -2452,9 +2480,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const long& value() const
@ -2585,9 +2613,9 @@ public:
val = NumberFormatter::format(_val);
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const unsigned long& value() const
@ -2678,9 +2706,9 @@ public:
val.append(" ]");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const std::vector<T>& value() const
@ -2799,9 +2827,9 @@ public:
ts = _val.timestamp();
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const DateTime& value() const
@ -2895,9 +2923,9 @@ public:
ts = _val.timestamp();
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const LocalDateTime& value() const
@ -2991,9 +3019,9 @@ public:
ts = _val;
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const Timestamp& value() const

View File

@ -150,7 +150,7 @@ class SmallObjectAllocator <char*>
///
/// The treshold between auto and heap allocation
/// is controlled through POCO_SMALL_OBJECT_SIZE compile
/// time constant, which on 32 or 64 systems defaults
/// time constant, which on 32 or 64-bit systems defaults
/// to 31 or 63 bytes respectively. This specialization
/// adds an extra byte to indicate the allocation strategy.
///

View File

@ -220,17 +220,6 @@ namespace Poco {
#endif
// Small object size in bytes. Where applicable (e.g.
// SmallObjectAllocator<char*> specialization of , Any, etc)
// objects longer than this value will be alocated on the heap.
// See Poco/SmallObjectAllocator.h for details.
#if (POCO_PTR_IS_64_BIT == 1)
#define POCO_SMALL_OBJECT_SIZE 63
#else
#define POCO_SMALL_OBJECT_SIZE 31
#endif
} // namespace Poco

View File

@ -44,35 +44,64 @@ namespace Poco {
namespace Dynamic {
Var::Var(): _pHolder(0)
Var::Var()
#ifdef POCO_NO_SOO
: _pHolder(0)
#endif
{
}
Var::Var(const char* pVal):
_pHolder(new VarHolderImpl<std::string>(pVal))
Var::Var(const char* pVal)
#ifdef POCO_NO_SOO
: _pHolder(new VarHolderImpl<std::string>(pVal)) { }
#else
{
construct(std::string(pVal));
}
#endif
Var::Var(const Var& other):
_pHolder(0)
Var::Var(const Var& other)
#ifdef POCO_NO_SOO
: _pHolder(0)
{
if (other._pHolder)
_pHolder = other._pHolder->clone();
}
#else
{
if ((this != &other) && !other.isEmpty())
construct(other);
}
#endif
Var::~Var()
{
delete _pHolder;
if(!isEmpty())
{
#ifndef POCO_NO_SOO
if(_placeholder.isLocal())
content()->~VarHolder();
else
#endif
delete content();
}
}
Var& Var::operator = (const Var& other)
Var& Var::operator = (const Var& rhs)
{
Var tmp(other);
#ifdef POCO_NO_SOO
Var tmp(rhs);
swap(tmp);
#else
if ((this != &rhs) && !rhs.isEmpty())
construct(rhs);
else if ((this != &rhs) && rhs.isEmpty())
_placeholder.erase();
#endif
return *this;
}
@ -320,8 +349,14 @@ bool Var::operator && (const Var& other) const
void Var::empty()
{
#ifdef POCO_NO_SOO
delete _pHolder;
_pHolder = 0;
#else
if (_placeholder.isLocal()) this->~Var();
else delete content();
_placeholder.erase();
#endif
}

View File

@ -279,22 +279,22 @@ public:
void convert(DateTime& /*val*/) const
{
throw BadCastException();
throw BadCastException("Cannot convert Array to DateTime");
}
void convert(LocalDateTime& /*ldt*/) const
{
throw BadCastException();
throw BadCastException("Cannot convert Array to LocalDateTime");
}
void convert(Timestamp& /*ts*/) const
{
throw BadCastException();
throw BadCastException("Cannot convert Array to Timestamp");
}
VarHolder* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const JSON::Array::Ptr& value() const

View File

@ -291,21 +291,24 @@ public:
void convert(DateTime& /*val*/) const
{
//TODO: val = _val;
throw NotImplementedException("Conversion not implemented: JSON:Object => DateTime");
}
void convert(LocalDateTime& /*ldt*/) const
{
//TODO: ldt = _val.timestamp();
throw NotImplementedException("Conversion not implemented: JSON:Object => LocalDateTime");
}
void convert(Timestamp& /*ts*/) const
{
//TODO: ts = _val.timestamp();
throw NotImplementedException("Conversion not implemented: JSON:Object => Timestamp");
}
VarHolderImpl* clone() const
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return new VarHolderImpl(_val);
return cloneHolder(pVarHolder, _val);
}
const JSON::Object::Ptr& value() const

View File

@ -393,8 +393,8 @@ private:
char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)];
friend class IPv4AddressImpl;
friend class IPv6AddressImpl;
friend class Poco::Net::Impl::IPv4AddressImpl;
friend class Poco::Net::Impl::IPv6AddressImpl;
};