mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-29 12:45:22 +01:00
Dynamic::Var SOO
Dynamic::Var small object optimization and some refactoring
This commit is contained in:
parent
54a92c59e5
commit
21da0129b6
3
.gitignore
vendored
3
.gitignore
vendored
@ -100,3 +100,6 @@ lib/
|
||||
lib64/
|
||||
pocomsg.h
|
||||
|
||||
# Temporary files #
|
||||
###################
|
||||
*.bak
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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*
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user