1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-11-30 13:07:19 +01:00

Update POCO to 1.11.0

This commit is contained in:
Sandu Liviu Catalin
2021-08-22 18:07:06 +03:00
parent 151077c799
commit 7a3d92d1d1
450 changed files with 25219 additions and 6528 deletions

View File

@@ -19,7 +19,7 @@
#include "Poco/KeyValueArgs.h"
#include "Poco/ValidArgs.h"
#include "Poco/ValidArgs.h"
#include "Poco/Mutex.h"
#include "Poco/Exception.h"
#include "Poco/FIFOEvent.h"
@@ -34,9 +34,9 @@
namespace Poco {
template <class TKey, class TValue, class TStrategy, class TMutex = FastMutex, class TEventMutex = FastMutex>
template <class TKey, class TValue, class TStrategy, class TMutex = FastMutex, class TEventMutex = FastMutex>
class AbstractCache
/// An AbstractCache is the interface of all caches.
/// An AbstractCache is the interface of all caches.
{
public:
FIFOEvent<const KeyValueArgs<TKey, TValue>, TEventMutex> Add;
@@ -83,7 +83,7 @@ public:
void update(const TKey& key, const TValue& val)
/// Adds the key value pair to the cache. Note that adding a NULL SharedPtr will fail!
/// If for the key already an entry exists, it will be overwritten.
/// The difference to add is that no remove or add events are thrown in this case,
/// The difference to add is that no remove or add events are thrown in this case,
/// just a simply silent update is performed
/// If the key does not exist the behavior is equal to add, ie. an add event is thrown
{
@@ -103,7 +103,7 @@ public:
void update(const TKey& key, SharedPtr<TValue > val)
/// Adds the key value pair to the cache. Note that adding a NULL SharedPtr will fail!
/// If for the key already an entry exists, it will be overwritten.
/// The difference to add is that no remove or add events are thrown in this case,
/// The difference to add is that no remove or add events are thrown in this case,
/// just an Update is thrown
/// If the key does not exist the behavior is equal to add, ie. an add event is thrown
{
@@ -176,6 +176,23 @@ public:
return result;
}
template <typename Fn>
void forEach(Fn&& fn) const
/// Iterates over all key-value pairs in the
/// cache, using a functor or lambda expression.
///
/// The given functor must take the key and value
/// as parameters. Note that the value is passed
/// as the actual value (or reference),
/// not a Poco::SharedPtr.
{
typename TMutex::ScopedLock lock(_mutex);
for (const auto& p: _data)
{
fn(p.first, *p.second);
}
}
protected:
mutable FIFOEvent<ValidArgs<TKey>> IsValid;
mutable FIFOEvent<KeySet> Replace;
@@ -214,7 +231,7 @@ protected:
KeyValueArgs<TKey, TValue> args(key, val);
Add.notify(this, args);
_data.insert(std::make_pair(key, SharedPtr<TValue>(new TValue(val))));
doReplace();
}
@@ -228,7 +245,7 @@ protected:
KeyValueArgs<TKey, TValue> args(key, *val);
Add.notify(this, args);
_data.insert(std::make_pair(key, val));
doReplace();
}
@@ -248,7 +265,7 @@ protected:
Update.notify(this, args);
it->second = SharedPtr<TValue>(new TValue(val));
}
doReplace();
}
@@ -268,11 +285,11 @@ protected:
Update.notify(this, args);
it->second = val;
}
doReplace();
}
void doRemove(Iterator it)
void doRemove(Iterator it)
/// Removes an entry from the cache. If the entry is not found
/// the remove is ignored.
{
@@ -300,7 +317,7 @@ protected:
return result;
}
SharedPtr<TValue> doGet(const TKey& key)
SharedPtr<TValue> doGet(const TKey& key)
/// Returns a SharedPtr of the cache entry, returns 0 if for
/// the key no value was found
{
@@ -308,7 +325,7 @@ protected:
SharedPtr<TValue> result;
if (it != _data.end())
{
{
// inform all strategies that a read-access to an element happens
Get.notify(this, key);
// ask all strategies if the key is valid

View File

@@ -38,7 +38,7 @@ public:
virtual void notify(Notification* pNf) const = 0;
virtual bool equals(const AbstractObserver& observer) const = 0;
virtual bool accepts(Notification* pNf) const = 0;
virtual bool accepts(Notification* pNf, const char* pName = 0) const = 0;
virtual AbstractObserver* clone() const = 0;
virtual void disable() = 0;
};

View File

@@ -159,7 +159,7 @@ public:
if (newCapacity > _capacity)
{
T* ptr = new T[newCapacity];
if (preserveContent)
if (preserveContent && _ptr)
{
std::memcpy(ptr, _ptr, _used * sizeof(T));
}
@@ -191,7 +191,7 @@ public:
if (newCapacity > 0)
{
ptr = new T[newCapacity];
if (preserveContent)
if (preserveContent && _ptr)
{
std::size_t newSz = _used < newCapacity ? _used : newCapacity;
std::memcpy(ptr, _ptr, newSz * sizeof(T));
@@ -266,10 +266,11 @@ public:
{
if (_used == other._used)
{
if (std::memcmp(_ptr, other._ptr, _used * sizeof(T)) == 0)
if (_ptr && other._ptr && std::memcmp(_ptr, other._ptr, _used * sizeof(T)) == 0)
{
return true;
}
else return _used == 0;
}
return false;
}

View File

@@ -116,7 +116,7 @@ public:
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(Pair<std::string>);
@@ -131,7 +131,7 @@ public:
{
throw BadCastException("Cannot cast Pair type to Int16");
}
void convert(Int32& val) const
{
throw BadCastException("Cannot cast Pair type to Int32");
@@ -151,7 +151,7 @@ public:
{
throw BadCastException("Cannot cast Pair type to UInt16");
}
void convert(UInt32& val) const
{
throw BadCastException("Cannot cast Pair type to UInt32");
@@ -189,9 +189,9 @@ public:
val.append("{ ");
Var key(_val.first());
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, _val.second());
val.append(" }");
val.append(" }");
}
void convert(Poco::DateTime&) const
@@ -213,7 +213,7 @@ public:
{
return cloneHolder(pVarHolder, _val);
}
const Pair<std::string>& value() const
{
return _val;
@@ -265,7 +265,7 @@ public:
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(Pair<int>);
@@ -280,7 +280,7 @@ public:
{
throw BadCastException("Cannot cast Pair type to Int16");
}
void convert(Int32& val) const
{
throw BadCastException("Cannot cast Pair type to Int32");
@@ -300,7 +300,7 @@ public:
{
throw BadCastException("Cannot cast Pair type to UInt16");
}
void convert(UInt32& val) const
{
throw BadCastException("Cannot cast Pair type to UInt32");
@@ -338,9 +338,9 @@ public:
val.append("{ ");
Var key(_val.first());
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, _val.second());
val.append(" }");
val.append(" }");
}
void convert(Poco::DateTime&) const
@@ -362,7 +362,7 @@ public:
{
return cloneHolder(pVarHolder, _val);
}
const Pair<int>& value() const
{
return _val;

View File

@@ -172,7 +172,7 @@ public:
{
_data.clear();
}
inline void swap(Struct& other)
/// Swap content of Struct with another Struct
{
@@ -264,7 +264,7 @@ public:
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(ValueType);
@@ -279,7 +279,7 @@ public:
{
throw BadCastException("Cannot cast Struct type to Int16");
}
void convert(Int32&) const
{
throw BadCastException("Cannot cast Struct type to Int32");
@@ -299,7 +299,7 @@ public:
{
throw BadCastException("Cannot cast Struct type to UInt16");
}
void convert(UInt32&) const
{
throw BadCastException("Cannot cast Struct type to UInt32");
@@ -339,7 +339,7 @@ public:
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
@@ -348,7 +348,7 @@ public:
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
@@ -373,7 +373,7 @@ public:
{
return cloneHolder(pVarHolder, _val);
}
const ValueType& value() const
{
return _val;
@@ -413,7 +413,7 @@ public:
{
return false;
}
std::size_t size() const
{
return _val.size();
@@ -525,7 +525,7 @@ public:
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
@@ -534,7 +534,7 @@ public:
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
@@ -711,7 +711,7 @@ public:
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
@@ -720,7 +720,7 @@ public:
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
@@ -897,7 +897,7 @@ public:
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
@@ -906,7 +906,7 @@ public:
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(" : ");
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");

View File

@@ -523,6 +523,9 @@ public:
bool isDateTime() const;
/// Returns true if stored value represents a date/time.
bool isUUID() const;
/// Returns true if stored value is a Poco::UUID.
std::size_t 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)
@@ -737,7 +740,7 @@ inline const std::type_info& Var::type() const
inline Var::ConstIterator Var::begin() const
{
if (isEmpty()) return ConstIterator(const_cast<Var*>(this), true);
if (size() == 0) return ConstIterator(const_cast<Var*>(this), true);
return ConstIterator(const_cast<Var*>(this), false);
}
@@ -749,7 +752,7 @@ inline Var::ConstIterator Var::end() const
inline Var::Iterator Var::begin()
{
if (isEmpty()) return Iterator(const_cast<Var*>(this), true);
if (size() == 0) return Iterator(const_cast<Var*>(this), true);
return Iterator(const_cast<Var*>(this), false);
}
@@ -896,6 +899,13 @@ inline bool Var::isDateTime() const
}
inline bool Var::isUUID() const
{
VarHolder* pHolder = content();
return pHolder ? pHolder->isUUID() : false;
}
inline std::size_t Var::size() const
{
VarHolder* pHolder = content();

View File

@@ -31,6 +31,7 @@
#include "Poco/UnicodeConverter.h"
#include "Poco/UTFString.h"
#include "Poco/UTF8String.h"
#include "Poco/UUID.h"
#include "Poco/Any.h"
#include "Poco/Exception.h"
#include <vector>
@@ -135,47 +136,51 @@ public:
/// (typeid) for the stored content.
virtual void convert(Int8& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(Int16& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(Int32& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(Int64& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(UInt8& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(UInt16& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(UInt32& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(UInt64& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(DateTime& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(LocalDateTime& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(Timestamp& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(UUID& val) const;
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
#ifndef POCO_INT64_IS_LONG
@@ -189,96 +194,100 @@ public:
#else
virtual void convert(long long& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to suport the conversion.
virtual void convert(unsigned long long & val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to suport the conversion.
#endif
virtual void convert(bool& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(float& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(double& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(char& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(std::string& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual void convert(Poco::UTF16String& val) const;
/// Throws BadCastException. Must be overriden in a type
/// Throws BadCastException. Must be overridden in a type
/// specialization in order to support the conversion.
virtual bool isArray() const;
/// Returns true.
virtual bool isVector() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isList() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isDeque() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isStruct() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isOrdered() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isInteger() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isSigned() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isNumeric() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isBoolean() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isString() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isDate() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isTime() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isDateTime() const;
/// Returns false. Must be properly overriden in a type
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual bool isUUID() const;
/// Returns false. Must be properly overridden in a type
/// specialization in order to support the diagnostic.
virtual std::size_t size() const;
/// Returns 1 iff Var is not empty or this function overriden.
/// Returns 1 iff Var is not empty or this function overridden.
protected:
VarHolder();
@@ -519,8 +528,16 @@ inline void VarHolder::convert(Timestamp& /*val*/) const
throw BadCastException("Can not convert to Timestamp");
}
inline void VarHolder::convert(UUID& /*val*/) const
{
throw BadCastException("Can not convert to UUID");
}
#ifndef POCO_INT64_IS_LONG
inline void VarHolder::convert(long& val) const
{
Int32 tmp;
@@ -536,8 +553,10 @@ inline void VarHolder::convert(unsigned long& val) const
val = tmp;
}
#else
inline void VarHolder::convert(long long& /*val*/) const
{
throw BadCastException("Can not convert to long long");
@@ -549,8 +568,10 @@ inline void VarHolder::convert(unsigned long long& /*val*/) const
throw BadCastException("Can not convert to unsigned long long");
}
#endif
inline void VarHolder::convert(bool& /*val*/) const
{
throw BadCastException("Can not convert to bool");
@@ -671,6 +692,12 @@ inline bool VarHolder::isDateTime() const
}
inline bool VarHolder::isUUID() const
{
return false;
}
inline std::size_t VarHolder::size() const
{
return 1u;
@@ -1026,7 +1053,6 @@ public:
return std::numeric_limits<Int16>::is_specialized;
}
bool isString() const
{
return false;
@@ -2750,6 +2776,11 @@ public:
ts = tmp.timestamp();
}
void convert(UUID& uuid) const
{
uuid.parse(_val);
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
@@ -3917,6 +3948,11 @@ public:
return true;
}
bool isUUID() const
{
return false;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
@@ -4047,6 +4083,11 @@ public:
return true;
}
bool isUUID() const
{
return false;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
@@ -4177,6 +4218,11 @@ public:
return true;
}
bool isUUID() const
{
return false;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
@@ -4186,6 +4232,102 @@ private:
};
template <>
class VarHolderImpl<UUID>: public VarHolder
{
public:
VarHolderImpl(const UUID& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(UUID);
}
void convert(std::string& val) const
{
val = _val.toString();
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const UUID& value() const
{
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 isBoolean() const
{
return false;
}
bool isString() const
{
return false;
}
bool isDate() const
{
return false;
}
bool isTime() const
{
return false;
}
bool isDateTime() const
{
return false;
}
bool isUUID() const
{
return true;
}
private:
VarHolderImpl();
VarHolderImpl(const VarHolderImpl&);
VarHolderImpl& operator = (const VarHolderImpl&);
Poco::UUID _val;
};
typedef std::vector<Var> Vector;
typedef std::deque<Var> Deque;
typedef std::list<Var> List;

View File

@@ -31,35 +31,71 @@ class FPEnvironmentImpl
protected:
enum RoundingModeImpl
{
#if defined(FE_DOWNWARD)
FP_ROUND_DOWNWARD_IMPL = FE_DOWNWARD,
#else
FP_ROUND_DOWNWARD_IMPL = 0,
#endif
#if defined(FE_UPWARD)
FP_ROUND_UPWARD_IMPL = FE_UPWARD,
#else
FP_ROUND_UPWARD_IMPL = 0,
#endif
#if defined(FE_TONEAREST)
FP_ROUND_TONEAREST_IMPL = FE_TONEAREST,
#else
FP_ROUND_TONEAREST_IMPL = 0,
#endif
#if defined(FE_TOWARDZERO)
FP_ROUND_TOWARDZERO_IMPL = FE_TOWARDZERO
#else
FP_ROUND_TOWARDZERO_IMPL = 0
#endif
};
enum FlagImpl
{
#if defined(FE_DIVBYZERO)
FP_DIVIDE_BY_ZERO_IMPL = FE_DIVBYZERO,
#else
FP_DIVIDE_BY_ZERO_IMPL = 0,
#endif
#if defined(FE_INEXACT)
FP_INEXACT_IMPL = FE_INEXACT,
#else
FP_INEXACT_IMPL = 0,
#endif
#if defined(FE_OVERFLOW)
FP_OVERFLOW_IMPL = FE_OVERFLOW,
#else
FP_OVERFLOW_IMPL = 0,
#endif
#if defined(FE_UNDERFLOW)
FP_UNDERFLOW_IMPL = FE_UNDERFLOW,
#else
FP_UNDERFLOW_IMPL = 0,
#endif
#if defined(FE_INVALID)
FP_INVALID_IMPL = FE_INVALID
#else
FP_INVALID_IMPL = 0
#endif
};
FPEnvironmentImpl();
FPEnvironmentImpl(const FPEnvironmentImpl& env);
~FPEnvironmentImpl();
FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
void keepCurrentImpl();
void keepCurrentImpl();
static void clearFlagsImpl();
static bool isFlagImpl(FlagImpl flag);
static bool isFlagImpl(FlagImpl flag);
static void setRoundingModeImpl(RoundingModeImpl mode);
static RoundingModeImpl getRoundingModeImpl();
static bool isInfiniteImpl(float value);
static bool isInfiniteImpl(float value);
static bool isInfiniteImpl(double value);
static bool isInfiniteImpl(long double value);
static bool isNaNImpl(float value);
static bool isNaNImpl(float value);
static bool isNaNImpl(double value);
static bool isNaNImpl(long double value);
static float copySignImpl(float target, float source);
static float copySignImpl(float target, float source);
static double copySignImpl(double target, double source);
static long double copySignImpl(long double target, long double source);
@@ -73,37 +109,61 @@ private:
//
inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
{
#if POCO_OS == POCO_OS_AIX
return ::isinf(value) != 0;
#else
return std::isinf(value) != 0;
#endif
}
inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
{
#if POCO_OS == POCO_OS_AIX
return ::isinf(value) != 0;
#else
return std::isinf(value) != 0;
#endif
}
inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
{
#if POCO_OS == POCO_OS_AIX
return ::isinf((double) value) != 0;
#else
return std::isinf((double) value) != 0;
#endif
}
inline bool FPEnvironmentImpl::isNaNImpl(float value)
{
#if POCO_OS == POCO_OS_AIX
return ::isnan(value) != 0;
#else
return std::isnan(value) != 0;
#endif
}
inline bool FPEnvironmentImpl::isNaNImpl(double value)
{
#if POCO_OS == POCO_OS_AIX
return ::isnan(value) != 0;
#else
return std::isnan(value) != 0;
#endif
}
inline bool FPEnvironmentImpl::isNaNImpl(long double value)
{
#if POCO_OS == POCO_OS_AIX
return ::isnan((double) value) != 0;
#else
return std::isnan((double) value) != 0;
#endif
}

View File

@@ -27,7 +27,7 @@ namespace Poco {
class FileImpl
{
protected:
enum Options
enum Options
{
OPT_FAIL_ON_OVERWRITE_IMPL = 0x01
};
@@ -65,6 +65,7 @@ protected:
FileSizeImpl totalSpaceImpl() const;
FileSizeImpl usableSpaceImpl() const;
FileSizeImpl freeSpaceImpl() const;
static void handleLastErrorImpl(int err, const std::string& path);
static void handleLastErrorImpl(const std::string& path);
private:

View File

@@ -45,7 +45,7 @@ public:
MemoryPool(std::size_t blockSize, int preAlloc = 0, int maxAlloc = 0);
/// Creates a MemoryPool for blocks with the given blockSize.
/// The number of blocks given in preAlloc are preallocated.
~MemoryPool();
void* get();
@@ -54,16 +54,16 @@ public:
///
/// If maxAlloc blocks are already allocated, an
/// OutOfMemoryException is thrown.
void release(void* ptr);
/// Releases a memory block and returns it to the pool.
std::size_t blockSize() const;
/// Returns the block size.
int allocated() const;
/// Returns the number of allocated blocks.
int available() const;
/// Returns the number of available blocks in the pool.
@@ -71,16 +71,16 @@ private:
MemoryPool();
MemoryPool(const MemoryPool&);
MemoryPool& operator = (const MemoryPool&);
void clear();
enum
{
BLOCK_RESERVE = 128
};
typedef std::vector<char*> BlockVec;
std::size_t _blockSize;
int _maxAlloc;
int _allocated;
@@ -94,7 +94,7 @@ private:
//
// Macro defining the default initial size of any
// FastMemoryPool; can be overriden by specifying
// FastMemoryPool; can be overridden by specifying
// FastMemoryPool pre-alloc at runtime.
#define POCO_FAST_MEMORY_POOL_PREALLOC 1000

View File

@@ -94,9 +94,9 @@ public:
return pObs && pObs->_pObject == _pObject && pObs->_method == _method;
}
bool accepts(Notification* pNf) const
bool accepts(Notification* pNf, const char* pName = 0) const
{
return dynamic_cast<N*>(pNf) != 0;
return dynamic_cast<N*>(pNf) && (!pName || pNf->name() == pName);
}
AbstractObserver* clone() const

View File

@@ -84,7 +84,7 @@ public:
Nullable(C&& value):
/// Creates a Nullable by moving the given value.
_value(value),
_value(std::forward<C>(value)),
_isNull(false),
_null()
{

View File

@@ -47,7 +47,7 @@ public:
{
return new C;
}
bool validateObject(P pObject)
/// Checks whether the object is still valid
/// and can be reused.
@@ -60,14 +60,14 @@ public:
{
return true;
}
void activateObject(P pObject)
/// Called before an object is handed out by the pool.
/// Also called for newly created objects, before
/// they are given out for the first time.
{
}
void deactivateObject(P pObject)
/// Called after an object has been given back to the
/// pool and the object is still valid (a prior call
@@ -77,7 +77,7 @@ public:
/// must not throw an exception.
{
}
void destroyObject(P pObject)
/// Destroy an object.
///
@@ -97,20 +97,20 @@ public:
{
return new C;
}
bool validateObject(Poco::AutoPtr<C> pObject)
{
return true;
}
void activateObject(Poco::AutoPtr<C> pObject)
{
}
void deactivateObject(Poco::AutoPtr<C> pObject)
{
}
void destroyObject(Poco::AutoPtr<C> pObject)
{
}
@@ -125,20 +125,20 @@ public:
{
return new C;
}
bool validateObject(Poco::SharedPtr<C> pObject)
{
return true;
}
void activateObject(Poco::SharedPtr<C> pObject)
{
}
void deactivateObject(Poco::SharedPtr<C> pObject)
{
}
void destroyObject(Poco::SharedPtr<C> pObject)
{
}
@@ -177,7 +177,7 @@ public:
{
poco_assert (capacity <= peakCapacity);
}
ObjectPool(const F& factory, std::size_t capacity, std::size_t peakCapacity):
/// Creates a new ObjectPool with the given PoolableObjectFactory,
/// capacity and peak capacity. The PoolableObjectFactory must have
@@ -189,7 +189,7 @@ public:
{
poco_assert (capacity <= peakCapacity);
}
~ObjectPool()
/// Destroys the ObjectPool.
{
@@ -205,7 +205,7 @@ public:
poco_unexpected();
}
}
P borrowObject(long timeoutMilliseconds = 0)
/// Obtains an object from the pool, or creates a new object if
/// possible.
@@ -217,22 +217,15 @@ public:
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_pool.empty())
{
P pObject = _pool.back();
_pool.pop_back();
return activateObject(pObject);
}
if (_size >= _peakCapacity)
if (_size >= _peakCapacity && _pool.empty())
{
if (timeoutMilliseconds == 0)
{
return 0;
}
while (_size >= _peakCapacity)
while (_size >= _peakCapacity && _pool.empty())
{
if ( !_availableCondition.tryWait(_mutex, timeoutMilliseconds))
if (!_availableCondition.tryWait(_mutex, timeoutMilliseconds))
{
// timeout
return 0;
@@ -240,10 +233,19 @@ public:
}
}
if (!_pool.empty())
{
P pObject = _pool.back();
_pool.pop_back();
return activateObject(pObject);
}
// _size < _peakCapacity
P pObject = _factory.createObject();
activateObject(pObject);
_size++;
return pObject;
}
@@ -260,6 +262,7 @@ public:
try
{
_pool.push_back(pObject);
_availableCondition.signal();
return;
}
catch (...)
@@ -276,19 +279,19 @@ public:
{
return _capacity;
}
std::size_t peakCapacity() const
{
return _peakCapacity;
}
std::size_t size() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return _size;
}
std::size_t available() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
@@ -310,12 +313,12 @@ protected:
}
return pObject;
}
private:
ObjectPool();
ObjectPool(const ObjectPool&);
ObjectPool& operator = (const ObjectPool&);
F _factory;
std::size_t _capacity;
std::size_t _peakCapacity;

View File

@@ -92,9 +92,9 @@ public:
return pObs && pObs->_pObject == _pObject && pObs->_method == _method;
}
bool accepts(Notification* pNf) const
bool accepts(Notification* pNf, const char* pName = 0) const
{
return dynamic_cast<N*>(pNf) != 0;
return dynamic_cast<N*>(pNf) && (!pName || pNf->name() == pName);
}
AbstractObserver* clone() const

View File

@@ -69,7 +69,7 @@ public:
Optional(C&& value):
/// Creates a Optional by moving the given value.
_value(value),
_value(std::forward<C>(value)),
_isSpecified(true)
{
}

View File

@@ -45,6 +45,7 @@ class Foundation_API PatternFormatter: public Formatter
/// * %I - message thread identifier (numeric)
/// * %N - node or host name
/// * %U - message source file path (empty string if not set)
/// * %O - message source file filename (empty string if not set)
/// * %u - message source line number (0 if not set)
/// * %w - message date/time abbreviated weekday (Mon, Tue, ...)
/// * %W - message date/time full weekday (Monday, Tuesday, ...)
@@ -143,6 +144,8 @@ private:
void parsePriorityNames();
static const std::string DEFAULT_PRIORITY_NAMES;
std::vector<PatternAction> _patternActions;
bool _localTime;
std::string _pattern;

View File

@@ -135,6 +135,7 @@
#define POCO_ARCH_AARCH64 0x0f
#define POCO_ARCH_ARM64 0x0f // same as POCO_ARCH_AARCH64
#define POCO_ARCH_RISCV64 0x10
#define POCO_ARCH_RISCV32 0x11
#if defined(__ALPHA) || defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA)
@@ -225,9 +226,14 @@
#elif defined(__AARCH64EB__)
#define POCO_ARCH POCO_ARCH_AARCH64
#define POCO_ARCH_BIG_ENDIAN 1
#elif defined(__riscv) && (__riscv_xlen == 64)
#define POCO_ARCH POCO_ARCH_RISCV64
#define POCO_ARCH_LITTLE_ENDIAN 1
#elif defined(__riscv)
#if (__riscv_xlen == 64)
#define POCO_ARCH POCO_ARCH_RISCV64
#define POCO_ARCH_LITTLE_ENDIAN 1
#elif(__riscv_xlen == 32)
#define POCO_ARCH POCO_ARCH_RISCV32
#define POCO_ARCH_LITTLE_ENDIAN 1
#endif
#endif
@@ -237,6 +243,7 @@
#define POCO_COMPILER_MSVC
#elif defined (__GNUC__)
#define POCO_COMPILER_GCC
// MinGW defines __GNUC__ so GCC and MinGW can coexist
#if defined (__MINGW32__) || defined (__MINGW64__)
#define POCO_COMPILER_MINGW
#endif

View File

@@ -22,10 +22,6 @@
#include "Poco/UnWindows.h"
#if defined(_MSC_VER) && !defined(POCO_MSVC_SECURE_WARNINGS) && !defined(_CRT_SECURE_NO_DEPRECATE)
#define _CRT_SECURE_NO_DEPRECATE
#endif
// Verify that we're built with the multithreaded
// versions of the runtime libraries
@@ -78,7 +74,6 @@
#pragma warning(disable:4351) // new behavior: elements of array '...' will be default initialized
#pragma warning(disable:4355) // 'this' : used in base member initializer list
#pragma warning(disable:4675) // resolved overload was found by argument-dependent lookup
#pragma warning(disable:4996) // VC++ 8.0 deprecation warnings
#endif

View File

@@ -480,7 +480,7 @@ SharedPtr<T> makeShared(Args&&... args)
template <typename T>
SharedPtr<T, ReferenceCounter, ReleaseArrayPolicy<T>> makeSharedArray(std::size_t size)
{
return new SharedPtr<T, ReferenceCounter, ReleaseArrayPolicy<T>>(new T[size]);
return SharedPtr<T, ReferenceCounter, ReleaseArrayPolicy<T>>(new T[size]);
}

View File

@@ -55,11 +55,11 @@
//
// In this scenario, std::ios::init() is called twice
// (the first time by the MyIOS constructor, the second
// time by the std::istream constructor), resulting in
// two locale objects being allocated, the pointer second
// one overwriting the pointer to the first one and thus
// time by the std::istream constructor), resulting in
// two locale objects being allocated, the pointer second
// one overwriting the pointer to the first one and thus
// causing a memory leak.
//
//
// The workaround is to call init() only once for each
// stream object - by the istream, ostream or iostream
// constructor, and not calling init() in ios-derived
@@ -77,6 +77,9 @@
# define POCO_IOS_INIT_HACK 1
// QNX with Dinkumware but not GNU C++ Library
# elif defined(__QNX__) && !defined(__GLIBCPP__)
# define POCO_IOS_INIT_HACK 1
// Linux with Clang libc++
# elif defined(__linux) && defined(_LIBCPP_VERSION)
# define POCO_IOS_INIT_HACK 1
# endif
#endif

View File

@@ -58,7 +58,7 @@ S trimRight(const S& str)
/// Returns a copy of str with all trailing
/// whitespace removed.
{
int pos = int(str.size()) - 1;
std::ptrdiff_t pos = static_cast<std::ptrdiff_t>(str.size()) - 1;
while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
return S(str, 0, pos + 1);
@@ -69,7 +69,7 @@ template <class S>
S& trimRightInPlace(S& str)
/// Removes all trailing whitespace in str.
{
int pos = int(str.size()) - 1;
std::ptrdiff_t pos = static_cast<std::ptrdiff_t>(str.size()) - 1;
while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
str.resize(pos + 1);
@@ -83,8 +83,8 @@ S trim(const S& str)
/// Returns a copy of str with all leading and
/// trailing whitespace removed.
{
int first = 0;
int last = int(str.size()) - 1;
std::ptrdiff_t first = 0;
std::ptrdiff_t last = static_cast<std::ptrdiff_t>(str.size()) - 1;
while (first <= last && Ascii::isSpace(str[first])) ++first;
while (last >= first && Ascii::isSpace(str[last])) --last;
@@ -97,8 +97,8 @@ template <class S>
S& trimInPlace(S& str)
/// Removes all leading and trailing whitespace in str.
{
int first = 0;
int last = int(str.size()) - 1;
std::ptrdiff_t first = 0;
std::ptrdiff_t last = static_cast<std::ptrdiff_t>(str.size()) - 1;
while (first <= last && Ascii::isSpace(str[first])) ++first;
while (last >= first && Ascii::isSpace(str[last])) --last;

View File

@@ -41,7 +41,7 @@ class Foundation_API ThreadPool
/// Threads in a thread pool are re-used once they become
/// available again.
/// The thread pool always keeps a minimum number of threads
/// running. If the demans for threads increases, additional
/// running. If the demand for threads increases, additional
/// threads are created. Once the demand for threads sinks
/// again, no-longer used threads are stopped and removed
/// from the pool.
@@ -72,8 +72,8 @@ public:
~ThreadPool();
/// Currently running threads will remain active
/// until they complete.
/// until they complete.
void addCapacity(int n);
/// Increases (or decreases, if n is negative)
/// the maximum number of threads.
@@ -126,7 +126,7 @@ public:
/// If used, this method should be the last action before
/// the thread pool is deleted.
///
/// Note: If a thread fails to stop within 10 seconds
/// Note: If a thread fails to stop within 10 seconds
/// (due to a programming error, for example), the
/// underlying thread object will not be deleted and
/// this method will return anyway. This allows for a

View File

@@ -287,7 +287,7 @@ public:
/// such as in a Windows path containing a drive letter, a dot segment (./)
/// is prepended in accordance with section 3.3 of RFC 3986.
void getPathSegments(std::vector<std::string>& segments);
void getPathSegments(std::vector<std::string>& segments) const;
/// Places the single path segments (delimited by slashes) into the
/// given vector.

View File

@@ -35,7 +35,7 @@
// Ax: alpha releases
// Bx: beta releases
//
#define POCO_VERSION 0x010A0100
#define POCO_VERSION 0x010B0000
#endif // Foundation_Version_INCLUDED

View File

@@ -21,8 +21,8 @@ namespace Poco {
//
// TraverseBase
//
TraverseBase::TraverseBase(DepthFun depthDeterminer, UInt16 maxDepth)
: _depthDeterminer(depthDeterminer), _maxDepth(maxDepth)
TraverseBase::TraverseBase(DepthFun depthDeterminer, UInt16 maxDepth):
_depthDeterminer(depthDeterminer), _maxDepth(maxDepth)
{
}
@@ -49,8 +49,8 @@ bool TraverseBase::isDirectory(Poco::File& file)
//
// ChildrenFirstTraverse
//
ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth)
: TraverseBase(depthDeterminer, maxDepth)
ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth):
TraverseBase(depthDeterminer, maxDepth)
{
}
@@ -61,10 +61,6 @@ const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished)
poco_check_ptr(isFinished);
poco_assert(!(*isFinished));
std::stack<DirectoryIterator> it;
//_depthDeterminer(it);
// go deeper into not empty directory
// (if depth limit allows)
bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth;
@@ -106,8 +102,8 @@ const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished)
//
// SiblingsFirstTraverse
//
SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth)
: TraverseBase(depthDeterminer, maxDepth)
SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFun depthDeterminer, UInt16 maxDepth):
TraverseBase(depthDeterminer, maxDepth)
{
_dirsStack.push(std::queue<std::string>());
}

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/Environment.h"
#include "Poco/Version.h"
#include <cstdlib>

View File

@@ -25,6 +25,11 @@
#include <iphlpapi.h>
#if defined(_MSC_VER)
#pragma warning(disable:4996) // deprecation warnings
#endif
namespace Poco {

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
// pull in platform identification macros needed below
#include "Poco/Platform.h"
#include "Poco/FPEnvironment.h"

View File

@@ -336,20 +336,22 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
struct stat st;
if (fstat(sd, &st) != 0)
{
int err = errno;
close(sd);
handleLastErrorImpl(_path);
handleLastErrorImpl(err, _path);
}
const long blockSize = st.st_blksize;
int dd;
if (options & OPT_FAIL_ON_OVERWRITE_IMPL) {
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, st.st_mode);
} else {
dd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, st.st_mode);
}
if (dd == -1)
{
int err = errno;
close(sd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
Buffer<char> buffer(blockSize);
try
@@ -361,7 +363,9 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
handleLastErrorImpl(path);
}
if (n < 0)
{
handleLastErrorImpl(_path);
}
}
catch (...)
{
@@ -372,11 +376,14 @@ void FileImpl::copyToImpl(const std::string& path, int options) const
close(sd);
if (fsync(dd) != 0)
{
int err = errno;
close(dd);
handleLastErrorImpl(path);
handleLastErrorImpl(err, path);
}
if (close(dd) != 0)
{
handleLastErrorImpl(path);
}
}
@@ -387,7 +394,7 @@ void FileImpl::renameToImpl(const std::string& path, int options)
struct stat st;
if (stat(path.c_str(), &st) == 0 && (options & OPT_FAIL_ON_OVERWRITE_IMPL))
throw FileExistsException(path, EEXIST);
throw FileExistsException(path, EEXIST);
if (rename(_path.c_str(), path.c_str()) != 0)
handleLastErrorImpl(_path);
@@ -490,43 +497,49 @@ FileImpl::FileSizeImpl FileImpl::freeSpaceImpl() const
}
void FileImpl::handleLastErrorImpl(const std::string& path)
void FileImpl::handleLastErrorImpl(int err, const std::string& path)
{
switch (errno)
switch (err)
{
case EIO:
throw IOException(path, errno);
throw IOException(path, err);
case EPERM:
throw FileAccessDeniedException("insufficient permissions", path, errno);
throw FileAccessDeniedException("insufficient permissions", path, err);
case EACCES:
throw FileAccessDeniedException(path, errno);
throw FileAccessDeniedException(path, err);
case ENOENT:
throw FileNotFoundException(path, errno);
throw FileNotFoundException(path, err);
case ENOTDIR:
throw OpenFileException("not a directory", path, errno);
throw OpenFileException("not a directory", path, err);
case EISDIR:
throw OpenFileException("not a file", path, errno);
throw OpenFileException("not a file", path, err);
case EROFS:
throw FileReadOnlyException(path, errno);
throw FileReadOnlyException(path, err);
case EEXIST:
throw FileExistsException(path, errno);
throw FileExistsException(path, err);
case ENOSPC:
throw FileException("no space left on device", path, errno);
throw FileException("no space left on device", path, err);
case EDQUOT:
throw FileException("disk quota exceeded", path, errno);
throw FileException("disk quota exceeded", path, err);
#if !defined(_AIX)
case ENOTEMPTY:
throw DirectoryNotEmptyException(path, errno);
throw DirectoryNotEmptyException(path, err);
#endif
case ENAMETOOLONG:
throw PathSyntaxException(path, errno);
throw PathSyntaxException(path, err);
case ENFILE:
case EMFILE:
throw FileException("too many open files", path, errno);
throw FileException("too many open files", path, err);
default:
throw FileException(Error::getMessage(errno), path, errno);
throw FileException(Error::getMessage(err), path, err);
}
}
void FileImpl::handleLastErrorImpl(const std::string& path)
{
handleLastErrorImpl(errno, path);
}
} // namespace Poco

View File

@@ -49,8 +49,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
{
for(std::string::const_iterator it = value.begin(), end = value.end(); it != end; ++it)
{
// Forward slash isn't strictly required by JSON spec, but some parsers expect it
if((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\') || (*it == '/'))
if((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\'))
{
std::string str = Poco::UTF8::escape(it, it + 1, true);
(obj.*write)(str.c_str(), str.size());

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/LocalDateTime.h"
#include "Poco/Timezone.h"
#include "Poco/Timespan.h"
@@ -99,7 +104,7 @@ LocalDateTime::LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff
adjustForTzd();
}
LocalDateTime::~LocalDateTime()
{
}
@@ -179,31 +184,31 @@ bool LocalDateTime::operator == (const LocalDateTime& dateTime) const
}
bool LocalDateTime::operator != (const LocalDateTime& dateTime) const
bool LocalDateTime::operator != (const LocalDateTime& dateTime) const
{
return utcTime() != dateTime.utcTime();
}
bool LocalDateTime::operator < (const LocalDateTime& dateTime) const
bool LocalDateTime::operator < (const LocalDateTime& dateTime) const
{
return utcTime() < dateTime.utcTime();
}
bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const
bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const
{
return utcTime() <= dateTime.utcTime();
}
bool LocalDateTime::operator > (const LocalDateTime& dateTime) const
bool LocalDateTime::operator > (const LocalDateTime& dateTime) const
{
return utcTime() > dateTime.utcTime();
}
bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const
bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const
{
return utcTime() >= dateTime.utcTime();
}
@@ -270,7 +275,7 @@ void LocalDateTime::determineTzd(bool adjust)
_tzd = (Timezone::utcOffset() + ((broken->tm_isdst == 1) ? 3600 : 0));
#else
std::tm broken;
#if defined(POCO_VXWORKS)
#if defined(POCO_VXWORKS) && (defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9)))))
if (localtime_r(&epochTime, &broken) != OK)
throw Poco::SystemException("cannot get local time");
#else
@@ -307,7 +312,7 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const
#else
local = std::mktime(&broken);
#endif
dstOffset = (broken.tm_isdst == 1) ? 3600 : 0;
return local;
}

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/NumberFormatter.h"
#include "Poco/MemoryStream.h"
#include <iomanip>
@@ -31,26 +36,22 @@
#endif
namespace Poco {
std::string NumberFormatter::format(bool value, BoolFormat format)
{
switch(format)
switch (format)
{
default:
case FMT_TRUE_FALSE:
if (value == true)
return "true";
return "false";
case FMT_YES_NO:
if (value == true)
return "yes";
return "no";
case FMT_ON_OFF:
if (value == true)
return "on";
return "off";
case FMT_YES_NO:
return value ? "yes" : "no";
case FMT_ON_OFF:
return value ? "on" : "off";
default: // including FMT_TRUE_FALSE:
return value ? "true" : "false";
}
}

View File

@@ -16,8 +16,8 @@
// +++ double conversion +++
#define double_conversion poco_double_conversion // don't collide with standalone double_conversion library
#define UNREACHABLE poco_bugcheck
// don't collide with standalone double_conversion library
#define double_conversion poco_double_conversion
#define UNIMPLEMENTED poco_bugcheck
#include "diy-fp.cc"
#include "cached-powers.cc"
@@ -51,7 +51,7 @@ void pad(std::string& str, int precision, int width, char prefix = ' ', char dec
std::string::size_type decSepPos = str.find(decSep);
if (decSepPos == std::string::npos)
{
str.append(1, '.');
str.append(1, decSep);
decSepPos = str.size() - 1;
}

View File

@@ -23,6 +23,7 @@
#include "Poco/Environment.h"
#include "Poco/NumberParser.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Path.h"
namespace Poco {
@@ -31,10 +32,11 @@ namespace Poco {
const std::string PatternFormatter::PROP_PATTERN = "pattern";
const std::string PatternFormatter::PROP_TIMES = "times";
const std::string PatternFormatter::PROP_PRIORITY_NAMES = "priorityNames";
const std::string PatternFormatter::DEFAULT_PRIORITY_NAMES = "Fatal,Critical,Error,Warning,Notice,Information,Debug,Trace";
PatternFormatter::PatternFormatter():
_localTime(false)
_localTime(false),
_priorityNames(DEFAULT_PRIORITY_NAMES)
{
parsePriorityNames();
}
@@ -42,7 +44,8 @@ PatternFormatter::PatternFormatter():
PatternFormatter::PatternFormatter(const std::string& format):
_localTime(false),
_pattern(format)
_pattern(format),
_priorityNames(DEFAULT_PRIORITY_NAMES)
{
parsePriorityNames();
parsePattern();
@@ -79,6 +82,7 @@ void PatternFormatter::format(const Message& msg, std::string& text)
case 'I': NumberFormatter::append(text, msg.getTid()); break;
case 'N': text.append(Environment::nodeName()); break;
case 'U': text.append(msg.getSourceFile() ? msg.getSourceFile() : ""); break;
case 'O': text.append(msg.getSourceFile() ? Path(msg.getSourceFile()).getFileName() : ""); break;
case 'u': NumberFormatter::append(text, msg.getSourceLine()); break;
case 'w': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()], 0, 3); break;
case 'W': text.append(DateTimeFormat::WEEKDAY_NAMES[dateTime.dayOfWeek()]); break;
@@ -230,48 +234,24 @@ std::string PatternFormatter::getProperty(const std::string& name) const
}
namespace
{
static std::string priorities[] =
{
"",
"Fatal",
"Critical",
"Error",
"Warning",
"Notice",
"Information",
"Debug",
"Trace"
};
}
void PatternFormatter::parsePriorityNames()
{
for (int i = 0; i <= 8; i++)
StringTokenizer st(_priorityNames, ",;", StringTokenizer::TOK_TRIM);
if (st.count() == 8)
{
_priorities[i] = priorities[i];
}
if (!_priorityNames.empty())
{
StringTokenizer st(_priorityNames, ",;", StringTokenizer::TOK_TRIM);
if (st.count() == 8)
for (int i = 1; i <= 8; i++)
{
for (int i = 1; i <= 8; i++)
{
_priorities[i] = st[i - 1];
}
_priorities[i] = st[i - 1];
}
else throw Poco::SyntaxException("priorityNames property must specify a comma-separated list of 8 property names");
}
else throw Poco::SyntaxException("priorityNames property must specify a comma-separated list of 8 property names");
}
const std::string& PatternFormatter::getPriorityName(int prio)
{
poco_assert (1 <= prio && prio <= 8);
return priorities[prio];
return _priorities[prio];
}

View File

@@ -173,6 +173,11 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
{
#if !defined(POCO_NO_FORK_EXEC)
// On some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number,
// which would closing all file descriptors up to that number extremely slow.
// We therefore limit the maximum number of file descriptors we close.
const long CLOSE_FD_MAX = 100000;
// We must not allocated memory after fork(),
// therefore allocate all required buffers first.
std::vector<char> envChars = getEnvironmentVariablesBuffer(env);
@@ -223,7 +228,10 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
// close all open file descriptors other than stdin, stdout, stderr
for (int i = 3; i < sysconf(_SC_OPEN_MAX); ++i)
long fdMax = sysconf(_SC_OPEN_MAX);
// on some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number
if (fdMax > CLOSE_FD_MAX) fdMax = CLOSE_FD_MAX;
for (long i = 3; i < fdMax; ++i)
{
close(i);
}

View File

@@ -411,9 +411,17 @@ bool ProcessImpl::isRunningImpl(PIDImpl pid)
{
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
bool result = true;
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
if (hProc)
{
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
CloseHandle(hProc);
}
else
{
result = false;
}
return result;
}

View File

@@ -211,10 +211,19 @@ bool ProcessImpl::isRunningImpl(PIDImpl pid)
{
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
bool result = true;
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
return result;}
if (hProc)
{
DWORD exitCode;
BOOL rc = GetExitCodeProcess(hProc, &exitCode);
if (!rc || exitCode != STILL_ACTIVE) result = false;
CloseHandle(hProc);
}
else
{
result = false;
}
return result;
}
void ProcessImpl::requestTerminationImpl(PIDImpl pid)

View File

@@ -16,6 +16,9 @@
#include "Poco/UnicodeConverter.h"
#include "Poco/Path.h"
#include "Poco/UnWindows.h"
#include "Poco/Error.h"
#include "Poco/Format.h"
#include "Poco/String.h"
namespace Poco {
@@ -48,7 +51,13 @@ void SharedLibraryImpl::loadImpl(const std::string& path, int /*flags*/)
std::wstring upath;
UnicodeConverter::toUTF16(path, upath);
_handle = LoadLibraryExW(upath.c_str(), 0, flags);
if (!_handle) throw LibraryLoadException(path);
if (!_handle)
{
DWORD errn = Error::last();
std::string err;
Poco::format(err, "Error %ul while loading [%s]: [%s]", errn, path, Poco::trim(Error::getMessage(errn)));
throw LibraryLoadException(err);
}
_path = path;
}

View File

@@ -107,10 +107,7 @@ void ThreadImpl::setPriorityImpl(int prio)
_pData->policy = SCHED_OTHER;
if (isRunningImpl())
{
struct sched_param par; struct MyStruct
{
};
struct sched_param par;
par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER);
if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
throw SystemException("cannot set thread priority");

View File

@@ -12,6 +12,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "Poco/Timezone.h"
#include <ctime>

View File

@@ -30,12 +30,16 @@ int Timezone::utcOffset()
return now - utc;
}
int Timezone::dst()
{
std::time_t now = std::time(NULL);
struct std::tm t;
#if defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9))))
if (localtime_r(&now, &t) != OK)
#else
if (!localtime_r(&now, &t))
#endif
throw Poco::SystemException("cannot get local time DST offset");
return t.tm_isdst == 1 ? 3600 : 0;
}
@@ -49,7 +53,7 @@ bool Timezone::isDst(const Timestamp& timestamp)
return tms->tm_isdst > 0;
}
std::string Timezone::name()
{
// format of TIMEZONE environment variable:
@@ -62,13 +66,13 @@ std::string Timezone::name()
return tz;
}
std::string Timezone::standardName()
{
return name();
}
std::string Timezone::dstName()
{
return name();

View File

@@ -615,7 +615,7 @@ void URI::removeDotSegments(bool removeLeading)
}
void URI::getPathSegments(std::vector<std::string>& segments)
void URI::getPathSegments(std::vector<std::string>& segments) const
{
getPathSegments(_path, segments);
}

View File

@@ -432,9 +432,10 @@ Var Var::parse(const std::string& val, std::string::size_type& pos)
std::string str = parseString(val, pos);
if (str == "false")
return false;
if (str == "true")
else if (str == "true")
return true;
else if (str == "null")
return Var();
bool isNumber = false;
bool isSigned = false;

View File

@@ -47,7 +47,8 @@ bool isJSONString(const Var& any)
any.type() == typeid(char*) ||
any.type() == typeid(Poco::DateTime) ||
any.type() == typeid(Poco::LocalDateTime) ||
any.type() == typeid(Poco::Timestamp);
any.type() == typeid(Poco::Timestamp) ||
any.type() == typeid(Poco::UUID);
}

View File

@@ -31,6 +31,7 @@ VarIterator::VarIterator(Var* pVar, bool positionEnd):
_pVar(pVar),
_position(positionEnd ? POSITION_END : 0)
{
if (!_pVar || _pVar->isEmpty()) throw InvalidAccessException("Cannot create iterator on empty Var");
}

View File

@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <cmath>
#include "bignum-dtoa.h"

View File

@@ -31,7 +31,7 @@
namespace double_conversion {
Bignum::Bignum()
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
: bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
for (int i = 0; i < kBigitCapacity; ++i) {
bigits_[i] = 0;
}
@@ -104,7 +104,7 @@ void Bignum::AssignDecimalString(Vector<const char> value) {
const int kMaxUint64DecimalDigits = 19;
Zero();
int length = value.length();
int pos = 0;
unsigned int pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
@@ -445,26 +445,27 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
mask >>= 2;
uint64_t this_value = base;
bool delayed_multipliciation = false;
bool delayed_multiplication = false;
const uint64_t max_32bits = 0xFFFFFFFF;
while (mask != 0 && this_value <= max_32bits) {
this_value = this_value * this_value;
// Verify that there is enough space in this_value to perform the
// multiplication. The first bit_size bits must be 0.
if ((power_exponent & mask) != 0) {
ASSERT(bit_size > 0);
uint64_t base_bits_mask =
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
bool high_bits_zero = (this_value & base_bits_mask) == 0;
if (high_bits_zero) {
this_value *= base;
} else {
delayed_multipliciation = true;
delayed_multiplication = true;
}
}
mask >>= 1;
}
AssignUInt64(this_value);
if (delayed_multipliciation) {
if (delayed_multiplication) {
MultiplyByUInt32(base);
}

View File

@@ -49,7 +49,6 @@ class Bignum {
void AssignPowerUInt16(uint16_t base, int exponent);
void AddUInt16(uint16_t operand);
void AddUInt64(uint64_t operand);
void AddBignum(const Bignum& other);
// Precondition: this >= other.
@@ -137,7 +136,7 @@ class Bignum {
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
int exponent_;
DISALLOW_COPY_AND_ASSIGN(Bignum);
DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
};
} // namespace double_conversion

View File

@@ -25,9 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include <math.h>
#include <climits>
#include <cmath>
#include <cstdarg>
#include "utils.h"
@@ -131,7 +131,6 @@ static const CachedPower kCachedPowers[] = {
{UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
};
static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
// Difference between the decimal exponents in the table above.
@@ -149,7 +148,7 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
int foo = kCachedPowersOffset;
int index =
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
ASSERT(0 <= index && index < kCachedPowersLength);
ASSERT(0 <= index && index < static_cast<int>(ARRAY_SIZE(kCachedPowers)));
CachedPower cached_power = kCachedPowers[index];
ASSERT(min_exponent <= cached_power.binary_exponent);
(void) max_exponent; // Mark variable as used.

View File

@@ -42,7 +42,7 @@ class DiyFp {
static const int kSignificandSize = 64;
DiyFp() : f_(0), e_(0) {}
DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {}
// this = this - other.
// The exponents of both numbers must be the same and the significand of this
@@ -76,22 +76,22 @@ class DiyFp {
void Normalize() {
ASSERT(f_ != 0);
uint64_t f = f_;
int e = e_;
uint64_t significand = f_;
int exponent = e_;
// This method is mainly called for normalizing boundaries. In general
// boundaries need to be shifted by 10 bits. We thus optimize for this case.
const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
while ((f & k10MSBits) == 0) {
f <<= 10;
e -= 10;
while ((significand & k10MSBits) == 0) {
significand <<= 10;
exponent -= 10;
}
while ((f & kUint64MSB) == 0) {
f <<= 1;
e--;
while ((significand & kUint64MSB) == 0) {
significand <<= 1;
exponent--;
}
f_ = f;
e_ = e;
f_ = significand;
e_ = exponent;
}
static DiyFp Normalize(const DiyFp& a) {

View File

@@ -25,8 +25,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits.h>
#include <math.h>
#include <climits>
#include <locale>
#include <cmath>
#include "double-conversion.h"
@@ -118,7 +119,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
StringBuilder* result_builder) const {
// Create a representation that is padded with zeros if needed.
if (decimal_point <= 0) {
// "0.00000decimal_rep".
// "0.00000decimal_rep" or "0.000decimal_rep00".
result_builder->AddCharacter('0');
if (digits_after_point > 0) {
result_builder->AddCharacter('.');
@@ -129,7 +130,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', remaining_digits);
}
} else if (decimal_point >= length) {
// "decimal_rep0000.00000" or "decimal_rep.0000"
// "decimal_rep0000.00000" or "decimal_rep.0000".
result_builder->AddSubstring(decimal_digits, length);
result_builder->AddPadding('0', decimal_point - length);
if (digits_after_point > 0) {
@@ -137,7 +138,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', digits_after_point);
}
} else {
// "decima.l_rep000"
// "decima.l_rep000".
ASSERT(digits_after_point > 0);
result_builder->AddSubstring(decimal_digits, decimal_point);
result_builder->AddCharacter('.');
@@ -249,6 +250,12 @@ bool DoubleToStringConverter::ToExponential(
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
char decimal_rep[kDecimalRepCapacity];
#ifndef NDEBUG
// Problem: there is an assert in StringBuilder::AddSubstring() that
// will pass this buffer to strlen(), and this buffer is not generally
// null-terminated.
memset(decimal_rep, 0, sizeof(decimal_rep));
#endif
int decimal_rep_length;
if (requested_digits == -1) {
@@ -348,7 +355,6 @@ static BignumDtoaMode DtoaToBignumDtoaMode(
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
default:
UNREACHABLE();
return BIGNUM_DTOA_SHORTEST;
}
}
@@ -415,20 +421,55 @@ void DoubleToStringConverter::DoubleToAscii(double v,
}
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
static bool ConsumeSubString(const char** current,
const char* end,
const char* substring) {
ASSERT(**current == *substring);
namespace {
inline char ToLower(char ch) {
static const std::ctype<char>& cType =
std::use_facet<std::ctype<char> >(std::locale::classic());
return cType.tolower(ch);
}
inline char Pass(char ch) {
return ch;
}
template <class Iterator, class Converter>
static inline bool ConsumeSubStringImpl(Iterator* current,
Iterator end,
const char* substring,
Converter converter) {
ASSERT(converter(**current) == *substring);
for (substring++; *substring != '\0'; substring++) {
++*current;
if (*current == end || **current != *substring) return false;
if (*current == end || converter(**current) != *substring) {
return false;
}
}
++*current;
return true;
}
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
template <class Iterator>
static bool ConsumeSubString(Iterator* current,
Iterator end,
const char* substring,
bool allow_case_insensibility) {
if (allow_case_insensibility) {
return ConsumeSubStringImpl(current, end, substring, ToLower);
} else {
return ConsumeSubStringImpl(current, end, substring, Pass);
}
}
// Consumes first character of the str is equal to ch
inline bool ConsumeFirstCharacter(char ch,
const char* str,
bool case_insensibility) {
return case_insensibility ? ToLower(ch) == str[0] : ch == str[0];
}
} // namespace
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
@@ -440,10 +481,36 @@ static bool ConsumeSubString(const char** current,
const int kMaxSignificantDigits = 772;
static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
static const uc16 kWhitespaceTable16[] = {
160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
};
static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
static bool isWhitespace(int x) {
if (x < 128) {
for (int i = 0; i < kWhitespaceTable7Length; i++) {
if (kWhitespaceTable7[i] == x) return true;
}
} else {
for (int i = 0; i < kWhitespaceTable16Length; i++) {
if (kWhitespaceTable16[i] == x) return true;
}
}
return false;
}
// Returns true if a nonspace found and false if the end has reached.
static inline bool AdvanceToNonspace(const char** current, const char* end) {
template <class Iterator>
static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
while (*current != end) {
if (**current != ' ') return true;
if (!isWhitespace(**current)) return true;
++*current;
}
return false;
@@ -468,10 +535,17 @@ static double SignedZero(bool sign) {
// because it constant-propagated the radix and concluded that the last
// condition was always true. By moving it into a separate function the
// compiler wouldn't warn anymore.
#ifdef _MSC_VER
#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
}
#pragma optimize("",on)
#else
static bool inline IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
}
#endif
// Returns true if 'c' is a character digit that is valid for the given radix.
// The 'a_character' should be 'a' or 'A'.
//
@@ -483,45 +557,128 @@ static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
return radix > 10 && c >= a_character && c < a_character + radix - 10;
}
// Returns true, when the iterator is equal to end.
template<class Iterator>
static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
if (separator == StringToDoubleConverter::kNoSeparator) {
++(*it);
return *it == end;
}
if (!isDigit(**it, base)) {
++(*it);
return *it == end;
}
++(*it);
if (*it == end) return true;
if (*it + 1 == end) return false;
if (**it == separator && isDigit(*(*it + 1), base)) {
++(*it);
}
return *it == end;
}
// Checks whether the string in the range start-end is a hex-float string.
// This function assumes that the leading '0x'/'0X' is already consumed.
//
// Hex float strings are of one of the following forms:
// - hex_digits+ 'p' ('+'|'-')? exponent_digits+
// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
template<class Iterator>
static bool IsHexFloatString(Iterator start,
Iterator end,
uc16 separator,
bool allow_trailing_junk) {
ASSERT(start != end);
Iterator current = start;
bool saw_digit = false;
while (isDigit(*current, 16)) {
saw_digit = true;
if (Advance(&current, separator, 16, end)) return false;
}
if (*current == '.') {
if (Advance(&current, separator, 16, end)) return false;
while (isDigit(*current, 16)) {
saw_digit = true;
if (Advance(&current, separator, 16, end)) return false;
}
}
if (!saw_digit) return false;
if (*current != 'p' && *current != 'P') return false;
if (Advance(&current, separator, 16, end)) return false;
if (*current == '+' || *current == '-') {
if (Advance(&current, separator, 16, end)) return false;
}
if (!isDigit(*current, 10)) return false;
if (Advance(&current, separator, 16, end)) return true;
while (isDigit(*current, 10)) {
if (Advance(&current, separator, 16, end)) return true;
}
return allow_trailing_junk || !AdvanceToNonspace(&current, end);
}
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
template <int radix_log_2>
static double RadixStringToIeee(const char* current,
const char* end,
//
// If parse_as_hex_float is true, then the string must be a valid
// hex-float.
template <int radix_log_2, class Iterator>
static double RadixStringToIeee(Iterator* current,
Iterator end,
bool sign,
uc16 separator,
bool parse_as_hex_float,
bool allow_trailing_junk,
double junk_string_value,
bool read_as_double,
const char** trailing_pointer) {
ASSERT(current != end);
bool* result_is_junk) {
ASSERT(*current != end);
ASSERT(!parse_as_hex_float ||
IsHexFloatString(*current, end, separator, allow_trailing_junk));
const int kDoubleSize = Double::kSignificandSize;
const int kSingleSize = Single::kSignificandSize;
const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
// Skip leading 0s.
while (*current == '0') {
++current;
if (current == end) {
*trailing_pointer = end;
return SignedZero(sign);
}
}
*result_is_junk = true;
int64_t number = 0;
int exponent = 0;
const int radix = (1 << radix_log_2);
// Whether we have encountered a '.' and are parsing the decimal digits.
// Only relevant if parse_as_hex_float is true.
bool post_decimal = false;
do {
// Skip leading 0s.
while (**current == '0') {
if (Advance(current, separator, radix, end)) {
*result_is_junk = false;
return SignedZero(sign);
}
}
while (true) {
int digit;
if (IsDecimalDigitForRadix(*current, radix)) {
digit = static_cast<char>(*current) - '0';
} else if (IsCharacterDigitForRadix(*current, radix, 'a')) {
digit = static_cast<char>(*current) - 'a' + 10;
} else if (IsCharacterDigitForRadix(*current, radix, 'A')) {
digit = static_cast<char>(*current) - 'A' + 10;
if (IsDecimalDigitForRadix(**current, radix)) {
digit = static_cast<char>(**current) - '0';
if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
digit = static_cast<char>(**current) - 'a' + 10;
if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
digit = static_cast<char>(**current) - 'A' + 10;
if (post_decimal) exponent -= radix_log_2;
} else if (parse_as_hex_float && **current == '.') {
post_decimal = true;
Advance(current, separator, radix, end);
ASSERT(*current != end);
continue;
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
break;
} else {
if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
break;
} else {
return junk_string_value;
@@ -542,17 +699,26 @@ static double RadixStringToIeee(const char* current,
int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
number >>= overflow_bits_count;
exponent = overflow_bits_count;
exponent += overflow_bits_count;
bool zero_tail = true;
for (;;) {
++current;
if (current == end || !isDigit(*current, radix)) break;
zero_tail = zero_tail && *current == '0';
exponent += radix_log_2;
if (Advance(current, separator, radix, end)) break;
if (parse_as_hex_float && **current == '.') {
// Just run over the '.'. We are just trying to see whether there is
// a non-zero digit somewhere.
Advance(current, separator, radix, end);
ASSERT(*current != end);
post_decimal = true;
}
if (!isDigit(**current, radix)) break;
zero_tail = zero_tail && **current == '0';
if (!post_decimal) exponent += radix_log_2;
}
if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
if (!parse_as_hex_float &&
!allow_trailing_junk &&
AdvanceToNonspace(current, end)) {
return junk_string_value;
}
@@ -574,15 +740,41 @@ static double RadixStringToIeee(const char* current,
}
break;
}
++current;
} while (current != end);
if (Advance(current, separator, radix, end)) break;
}
ASSERT(number < ((int64_t)1 << kSignificandSize));
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
*trailing_pointer = current;
*result_is_junk = false;
if (exponent == 0) {
if (parse_as_hex_float) {
ASSERT(**current == 'p' || **current == 'P');
Advance(current, separator, radix, end);
ASSERT(*current != end);
bool is_negative = false;
if (**current == '+') {
Advance(current, separator, radix, end);
ASSERT(*current != end);
} else if (**current == '-') {
is_negative = true;
Advance(current, separator, radix, end);
ASSERT(*current != end);
}
int written_exponent = 0;
while (IsDecimalDigitForRadix(**current, 10)) {
// No need to read exponents if they are too big. That could potentially overflow
// the `written_exponent` variable.
if (abs(written_exponent) <= 100 * Double::kMaxExponent) {
written_exponent = 10 * written_exponent + **current - '0';
}
if (Advance(current, separator, radix, end)) break;
}
if (is_negative) written_exponent = -written_exponent;
exponent += written_exponent;
}
if (exponent == 0 || number == 0) {
if (sign) {
if (number == 0) return -0.0;
number = -number;
@@ -591,17 +783,18 @@ static double RadixStringToIeee(const char* current,
}
ASSERT(number != 0);
return Double(DiyFp(number, exponent)).value();
double result = Double(DiyFp(number, exponent)).value();
return sign ? -result : result;
}
template <class Iterator>
double StringToDoubleConverter::StringToIeee(
const char* input,
Iterator input,
int length,
int* processed_characters_count,
bool read_as_double) const {
const char* current = input;
const char* end = input + length;
bool read_as_double,
int* processed_characters_count) const {
Iterator current = input;
Iterator end = input + length;
*processed_characters_count = 0;
@@ -609,6 +802,7 @@ double StringToDoubleConverter::StringToIeee(
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0;
// To make sure that iterator dereferencing is valid the following
// convention is used:
@@ -648,7 +842,7 @@ double StringToDoubleConverter::StringToIeee(
if (*current == '+' || *current == '-') {
sign = (*current == '-');
++current;
const char* next_non_space = current;
Iterator next_non_space = current;
// Skip following spaces (if allowed).
if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
if (!allow_spaces_after_sign && (current != next_non_space)) {
@@ -658,8 +852,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (infinity_symbol_ != NULL) {
if (*current == infinity_symbol_[0]) {
if (!ConsumeSubString(&current, end, infinity_symbol_)) {
if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) {
if (!ConsumeSubString(&current, end, infinity_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -677,8 +871,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (nan_symbol_ != NULL) {
if (*current == nan_symbol_[0]) {
if (!ConsumeSubString(&current, end, nan_symbol_)) {
if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) {
if (!ConsumeSubString(&current, end, nan_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -697,8 +891,7 @@ double StringToDoubleConverter::StringToIeee(
bool leading_zero = false;
if (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -706,31 +899,39 @@ double StringToDoubleConverter::StringToIeee(
leading_zero = true;
// It could be hexadecimal value.
if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
(*current == 'x' || *current == 'X')) {
++current;
if (current == end || !isDigit(*current, 16)) {
return junk_string_value_; // "0x".
if (current == end) return junk_string_value_; // "0x"
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
IsHexFloatString(current, end, separator_, allow_trailing_junk);
if (!parse_as_hex_float && !isDigit(*current, 16)) {
return junk_string_value_;
}
const char* tail_pointer = NULL;
double result = RadixStringToIeee<4>(current,
bool result_is_junk;
double result = RadixStringToIeee<4>(&current,
end,
sign,
separator_,
parse_as_hex_float,
allow_trailing_junk,
junk_string_value_,
read_as_double,
&tail_pointer);
if (tail_pointer != NULL) {
if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
*processed_characters_count = static_cast<int>(tail_pointer - input);
&result_is_junk);
if (!result_is_junk) {
if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
*processed_characters_count = static_cast<int>(current - input);
}
return result;
}
// Ignore leading zeros in the integer part.
while (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -751,8 +952,7 @@ double StringToDoubleConverter::StringToIeee(
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
octal = octal && *current < '8';
++current;
if (current == end) goto parsing_done;
if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
if (significant_digits == 0) {
@@ -763,8 +963,7 @@ double StringToDoubleConverter::StringToIeee(
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
if (significant_digits == 0 && !leading_zero) {
return junk_string_value_;
} else {
@@ -777,8 +976,7 @@ double StringToDoubleConverter::StringToIeee(
// Integer part consists of 0 or is absent. Significant digits start after
// leading zeros (if any).
while (*current == '0') {
++current;
if (current == end) {
if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -798,8 +996,7 @@ double StringToDoubleConverter::StringToIeee(
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
++current;
if (current == end) goto parsing_done;
if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
}
@@ -815,20 +1012,23 @@ double StringToDoubleConverter::StringToIeee(
if (*current == 'e' || *current == 'E') {
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
Iterator junk_begin = current;
++current;
if (current == end) {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
char sign = '+';
char exponen_sign = '+';
if (*current == '+' || *current == '-') {
sign = static_cast<char>(*current);
exponen_sign = static_cast<char>(*current);
++current;
if (current == end) {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -838,6 +1038,7 @@ double StringToDoubleConverter::StringToIeee(
if (current == end || *current < '0' || *current > '9') {
if (allow_trailing_junk) {
current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -859,7 +1060,7 @@ double StringToDoubleConverter::StringToIeee(
++current;
} while (current != end && *current >= '0' && *current <= '9');
exponent += (sign == '-' ? -num : num);
exponent += (exponen_sign == '-' ? -num : num);
}
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
@@ -877,15 +1078,18 @@ double StringToDoubleConverter::StringToIeee(
if (octal) {
double result;
const char* tail_pointer = NULL;
result = RadixStringToIeee<3>(buffer,
bool result_is_junk;
char* start = buffer;
result = RadixStringToIeee<3>(&start,
buffer + buffer_pos,
sign,
separator_,
false, // Don't parse as hex_float.
allow_trailing_junk,
junk_string_value_,
read_as_double,
&tail_pointer);
ASSERT(tail_pointer != NULL);
&result_is_junk);
ASSERT(!result_is_junk);
*processed_characters_count = static_cast<int>(current - input);
return result;
}
@@ -908,4 +1112,38 @@ double StringToDoubleConverter::StringToIeee(
return sign? -converted: converted;
}
double StringToDoubleConverter::StringToDouble(
const char* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, true, processed_characters_count);
}
double StringToDoubleConverter::StringToDouble(
const uc16* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, true, processed_characters_count);
}
float StringToDoubleConverter::StringToFloat(
const char* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length, false,
processed_characters_count));
}
float StringToDoubleConverter::StringToFloat(
const uc16* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length, false,
processed_characters_count));
}
} // namespace double_conversion

View File

@@ -294,13 +294,18 @@ class DoubleToStringConverter {
// should be at least kBase10MaximalLength + 1 characters long.
static const int kBase10MaximalLength = 17;
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
// after it has been casted to a single-precision float. That is, in this
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
// Converts the given double 'v' to digit characters. 'v' must not be NaN,
// +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
// applies to 'v' after it has been casted to a single-precision float. That
// is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
// -Infinity.
//
// The result should be interpreted as buffer * 10^(point-length).
//
// The digits are written to the buffer in the platform's charset, which is
// often UTF-8 (with ASCII-range digits) but may be another charset, such
// as EBCDIC.
//
// The output depends on the given mode:
// - SHORTEST: produce the least amount of digits for which the internal
// identity requirement is still satisfied. If the digits are printed
@@ -374,7 +379,7 @@ class DoubleToStringConverter {
const int max_leading_padding_zeroes_in_precision_mode_;
const int max_trailing_padding_zeroes_in_precision_mode_;
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
};
@@ -389,9 +394,13 @@ class StringToDoubleConverter {
ALLOW_TRAILING_JUNK = 4,
ALLOW_LEADING_SPACES = 8,
ALLOW_TRAILING_SPACES = 16,
ALLOW_SPACES_AFTER_SIGN = 32
ALLOW_SPACES_AFTER_SIGN = 32,
ALLOW_CASE_INSENSIBILITY = 64,
ALLOW_HEX_FLOATS = 128,
};
static const uc16 kNoSeparator = '\0';
// Flags should be a bit-or combination of the possible Flags-enum.
// - NO_FLAGS: no special flags.
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
@@ -415,11 +424,19 @@ class StringToDoubleConverter {
// junk, too.
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
// a double literal.
// - ALLOW_LEADING_SPACES: skip over leading spaces.
// - ALLOW_TRAILING_SPACES: ignore trailing spaces.
// - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.
// - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
// new-lines, and tabs.
// - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
// Ex: StringToDouble("- 123.2") -> -123.2.
// StringToDouble("+ 123.2") -> 123.2
// - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
// infinity and nan.
// - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
// This *must* start with "0x" and separate the exponent with "p".
// Examples: 0x1.2p3 == 9.0
// 0x10.1p0 == 16.0625
// ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
//
// empty_string_value is returned when an empty string is given as input.
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
@@ -444,6 +461,12 @@ class StringToDoubleConverter {
// - they must not have the same first character.
// - they must not start with digits.
//
// If the separator character is not kNoSeparator, then that specific
// character is ignored when in between two valid digits of the significant.
// It is not allowed to appear in the exponent.
// It is not allowed to lead or trail the number.
// It is not allowed to appear twice next to each other.
//
// Examples:
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
// empty_string_value = 0.0,
@@ -483,16 +506,26 @@ class StringToDoubleConverter {
// StringToDouble("01239E45") -> 1239e45.
// StringToDouble("-infinity") -> NaN // junk_string_value.
// StringToDouble("NaN") -> NaN // junk_string_value.
//
// flags = NO_FLAGS,
// separator = ' ':
// StringToDouble("1 2 3 4") -> 1234.0
// StringToDouble("1 2") -> NaN // junk_string_value
// StringToDouble("1 000 000.0") -> 1000000.0
// StringToDouble("1.000 000") -> 1.0
// StringToDouble("1.0e1 000") -> NaN // junk_string_value
StringToDoubleConverter(int flags,
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
const char* nan_symbol)
const char* nan_symbol,
uc16 separator = kNoSeparator)
: flags_(flags),
empty_string_value_(empty_string_value),
junk_string_value_(junk_string_value),
infinity_symbol_(infinity_symbol),
nan_symbol_(nan_symbol) {
nan_symbol_(nan_symbol),
separator_(separator) {
}
// Performs the conversion.
@@ -502,19 +535,24 @@ class StringToDoubleConverter {
// in the 'processed_characters_count'. Trailing junk is never included.
double StringToDouble(const char* buffer,
int length,
int* processed_characters_count) const {
return StringToIeee(buffer, length, processed_characters_count, true);
}
int* processed_characters_count) const;
// Same as StringToDouble above but for 16 bit characters.
double StringToDouble(const uc16* buffer,
int length,
int* processed_characters_count) const;
// Same as StringToDouble but reads a float.
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
// due to potential double-rounding.
float StringToFloat(const char* buffer,
int length,
int* processed_characters_count) const {
return static_cast<float>(StringToIeee(buffer, length,
processed_characters_count, false));
}
int* processed_characters_count) const;
// Same as StringToFloat above but for 16 bit characters.
float StringToFloat(const uc16* buffer,
int length,
int* processed_characters_count) const;
private:
const int flags_;
@@ -522,13 +560,15 @@ class StringToDoubleConverter {
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
const uc16 separator_;
double StringToIeee(const char* buffer,
template <class Iterator>
double StringToIeee(Iterator start_pointer,
int length,
int* processed_characters_count,
bool read_as_double) const;
bool read_as_double,
int* processed_characters_count) const;
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
};
} // namespace double_conversion

View File

@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <cmath>
#include "fixed-dtoa.h"
#include "ieee.h"
@@ -98,7 +98,7 @@ class UInt128 {
return high_bits_ == 0 && low_bits_ == 0;
}
int BitAt(int position) {
int BitAt(int position) const {
if (position >= 64) {
return static_cast<int>(high_bits_ >> (position - 64)) & 1;
} else {
@@ -259,7 +259,8 @@ static void FillFractionals(uint64_t fractionals, int exponent,
fractionals -= static_cast<uint64_t>(digit) << point;
}
// If the first bit after the point is set we have to round up.
if (((fractionals >> (point - 1)) & 1) == 1) {
ASSERT(fractionals == 0 || point - 1 >= 0);
if ((fractionals != 0) && ((fractionals >> (point - 1)) & 1) == 1) {
RoundUp(buffer, length, decimal_point);
}
} else { // We need 128 bits.

View File

@@ -47,6 +47,8 @@ class Double {
static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
static const int kSignificandSize = 53;
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kMaxExponent = 0x7FF - kExponentBias;
Double() : d64_(0) {}
explicit Double(double d) : d64_(double_to_uint64(d)) {}
@@ -99,7 +101,7 @@ class Double {
}
double PreviousDouble() const {
if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity();
if (d64_ == (kInfinity | kSignMask)) return -Infinity();
if (Sign() < 0) {
return Double(d64_ + 1).value();
} else {
@@ -222,9 +224,7 @@ class Double {
}
private:
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kDenormalExponent = -kExponentBias + 1;
static const int kMaxExponent = 0x7FF - kExponentBias;
static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
@@ -257,7 +257,7 @@ class Double {
(biased_exponent << kPhysicalSignificandSize);
}
DISALLOW_COPY_AND_ASSIGN(Double);
DC_DISALLOW_COPY_AND_ASSIGN(Double);
};
class Single {
@@ -394,7 +394,7 @@ class Single {
const uint32_t d32_;
DISALLOW_COPY_AND_ASSIGN(Single);
DC_DISALLOW_COPY_AND_ASSIGN(Single);
};
} // namespace double_conversion

View File

@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
#define PCRE_MINOR 43
#define PCRE_MINOR 44
#define PCRE_PRERELEASE
#define PCRE_DATE 2019-02-23
#define PCRE_DATE 020-02-12
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2018 University of Cambridge
Copyright (c) 1997-2020 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ COMPILE_PCREx macro will already be appropriately set. */
/* Macro for setting individual bits in class bitmaps. */
#define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7))
#define SETBIT(a,b) a[(b)/8] |= (1U << ((b)&7))
/* Maximum length value to check against when making sure that the integer that
holds the compiled pattern length does not overflow. We make it a bit less than
@@ -131,8 +131,8 @@ overrun before it actually does run off the end of the data block. */
/* Private flags added to firstchar and reqchar. */
#define REQ_CASELESS (1 << 0) /* Indicates caselessness */
#define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */
#define REQ_CASELESS (1U << 0) /* Indicates caselessness */
#define REQ_VARY (1U << 1) /* Reqchar followed non-literal item */
/* Negative values for the firstchar and reqchar flags */
#define REQ_UNSET (-2)
#define REQ_NONE (-1)
@@ -3301,7 +3301,7 @@ for(;;)
if ((*xclass_flags & XCL_MAP) == 0)
{
/* No bits are set for characters < 256. */
if (list[1] == 0) return TRUE;
if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0;
/* Might be an empty repeat. */
continue;
}
@@ -3613,7 +3613,7 @@ for(;;)
if (chr > 255) break;
class_bitset = (pcre_uint8 *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
if ((class_bitset[chr >> 3] & (1U << (chr & 7))) != 0) return FALSE;
break;
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
@@ -7132,17 +7132,19 @@ for (;; ptr++)
int n = 0;
ptr++;
while(IS_DIGIT(*ptr))
{
n = n * 10 + *ptr++ - CHAR_0;
if (n > 255)
{
*errorcodeptr = ERR38;
goto FAILED;
}
}
if (*ptr != CHAR_RIGHT_PARENTHESIS)
{
*errorcodeptr = ERR39;
goto FAILED;
}
if (n > 255)
{
*errorcodeptr = ERR38;
goto FAILED;
}
*code++ = n;
PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */
PUT(code, LINK_SIZE, 0); /* Default length */
@@ -7458,7 +7460,7 @@ for (;; ptr++)
{
open_capitem *oc;
recno = GET2(slot, 0);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -7644,8 +7646,8 @@ for (;; ptr++)
/* Can't determine a first byte now */
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
zerofirstchar = firstchar;
zerofirstcharflags = firstcharflags;
zerofirstchar = firstchar;
zerofirstcharflags = firstcharflags;
continue;
@@ -8069,7 +8071,7 @@ for (;; ptr++)
item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
cd->backref_map |= (recno < 32)? (1U << recno) : 1;
if (recno > cd->top_backref) cd->top_backref = recno;
/* Check to see if this back reference is recursive, that it, it
@@ -8682,7 +8684,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_anchored(scode, new_map, cd, atomcount)) return FALSE;
}
@@ -8694,6 +8696,7 @@ do {
}
/* Condition; not anchored if no second branch */
else if (op == OP_COND)
{
if (scode[GET(scode,1)] != OP_ALT) return FALSE;
@@ -8809,7 +8812,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
int new_map = bracket_map | ((n < 32)? (1 << n) : 1);
int new_map = bracket_map | ((n < 32)? (1U << n) : 1);
if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE;
}

View File

@@ -289,7 +289,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE 8.43"
#define PACKAGE_STRING "PCRE 8.44"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre"
@@ -298,7 +298,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "8.43"
#define PACKAGE_VERSION "8.44"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -400,7 +400,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* #undef SUPPORT_VALGRIND */
/* Version number of package */
#define VERSION "8.43"
#define VERSION "8.44"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

View File

@@ -3937,10 +3937,10 @@ static sljit_s32 character_to_int32(pcre_uchar chr)
sljit_s32 value = (sljit_s32)chr;
#if defined COMPILE_PCRE8
#define SSE2_COMPARE_TYPE_INDEX 0
return (value << 24) | (value << 16) | (value << 8) | value;
return ((unsigned int)value << 24) | ((unsigned int)value << 16) | ((unsigned int)value << 8) | (unsigned int)value;
#elif defined COMPILE_PCRE16
#define SSE2_COMPARE_TYPE_INDEX 1
return (value << 16) | value;
return ((unsigned int)value << 16) | value;
#elif defined COMPILE_PCRE32
#define SSE2_COMPARE_TYPE_INDEX 2
return value;
@@ -8506,7 +8506,7 @@ if (opcode == OP_ONCE)
/* We temporarily encode the needs_control_head in the lowest bit.
Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns
the same value for small signed numbers (including negative numbers). */
BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
BACKTRACK_AS(bracket_backtrack)->u.framesize = ((unsigned int)BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0);
}
return cc + repeat_length;
}
@@ -9001,7 +9001,7 @@ if (exact > 1)
#ifdef SUPPORT_UTF
&& !common->utf
#endif
)
&& type != OP_ANYNL && type != OP_EXTUNI)
{
OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact));
add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0));

View File

@@ -25,13 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include <climits>
#include <cstdarg>
#include "strtod.h"
#include "bignum.h"
#include "cached-powers.h"
#include "ieee.h"
#include "strtod.h"
namespace double_conversion {
@@ -205,7 +205,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
// the same problem.
return false;
#endif
#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
int read_digits;
// The trimmed input fits into a double.
@@ -243,6 +243,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
}
}
return false;
#endif
}
@@ -264,7 +265,6 @@ static DiyFp AdjustmentPowerOfTen(int exponent) {
case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
default:
UNREACHABLE();
return DiyFp(0, 0);
}
}
@@ -287,7 +287,7 @@ static bool DiyFpStrtod(Vector<const char> buffer,
const int kDenominator = 1 << kDenominatorLog;
// Move the remaining decimals into the exponent.
exponent += remaining_decimals;
int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
int old_e = input.e();
input.Normalize();
@@ -472,6 +472,30 @@ double Strtod(Vector<const char> buffer, int exponent) {
}
}
static float SanitizedDoubletof(double d) {
ASSERT(d >= 0.0);
// ASAN has a sanitize check that disallows casting doubles to floats if
// they are too big.
// https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
// The behavior should be covered by IEEE 754, but some projects use this
// flag, so work around it.
float max_finite = 3.4028234663852885981170418348451692544e+38;
// The half-way point between the max-finite and infinity value.
// Since infinity has an even significand everything equal or greater than
// this value should become infinity.
double half_max_finite_infinity =
3.40282356779733661637539395458142568448e+38;
if (d >= max_finite) {
if (d >= half_max_finite_infinity) {
return Single::Infinity();
} else {
return max_finite;
}
} else {
return static_cast<float>(d);
}
}
float Strtof(Vector<const char> buffer, int exponent) {
char copy_buffer[kMaxSignificantDecimalDigits];
Vector<const char> trimmed;
@@ -483,7 +507,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
float float_guess = static_cast<float>(double_guess);
float float_guess = SanitizedDoubletof(double_guess);
if (float_guess == double_guess) {
// This shortcut triggers for integer values.
return float_guess;
@@ -506,15 +530,15 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_next = Double(double_guess).NextDouble();
double double_previous = Double(double_guess).PreviousDouble();
float f1 = static_cast<float>(double_previous);
float f1 = SanitizedDoubletof(double_previous);
float f2 = float_guess;
float f3 = static_cast<float>(double_next);
float f3 = SanitizedDoubletof(double_next);
float f4;
if (is_correct) {
f4 = f3;
} else {
double double_next2 = Double(double_next).NextDouble();
f4 = static_cast<float>(double_next2);
f4 = SanitizedDoubletof(double_next2);
}
(void) f2; // Mark variable as used.
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
@@ -529,7 +553,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
(f1 == f2 && f2 != f3 && f3 == f4) ||
(f1 == f2 && f2 == f3 && f3 != f4));
// guess and next are the two possible canditates (in the same way that
// guess and next are the two possible candidates (in the same way that
// double_guess was the lower candidate for a double-precision guess).
float guess = f1;
float next = f4;

View File

@@ -28,10 +28,10 @@
#ifndef DOUBLE_CONVERSION_UTILS_H_
#define DOUBLE_CONVERSION_UTILS_H_
#include <stdlib.h>
#include <string.h>
#include <cstdlib>
#include <cstring>
#include <assert.h>
#include <cassert>
#ifndef ASSERT
#define ASSERT(condition) \
assert(condition);
@@ -39,9 +39,30 @@
#ifndef UNIMPLEMENTED
#define UNIMPLEMENTED() (abort())
#endif
#ifndef DOUBLE_CONVERSION_NO_RETURN
#ifdef _MSC_VER
#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
#else
#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
#endif
#endif
#ifndef UNREACHABLE
#ifdef _MSC_VER
void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
inline void abort_noreturn() { abort(); }
#define UNREACHABLE() (abort_noreturn())
#else
#define UNREACHABLE() (abort())
#endif
#endif
#ifndef DOUBLE_CONVERSION_UNUSED
#ifdef __GNUC__
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
#endif
// Double operations detection based on target architecture.
// Linux uses a 80bit wide floating point stack on x86. This induces double
@@ -53,19 +74,39 @@
// the output of the division with the expected result. (Inlining must be
// disabled.)
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
//
// For example:
/*
// -- in div.c
double Div_double(double x, double y) { return x / y; }
// -- in main.c
double Div_double(double x, double y); // Forward declaration.
int main(int argc, char** argv) {
return Div_double(89255.0, 1e22) == 89255e-22;
}
*/
// Run as follows ./main || echo "correct"
//
// If it prints "correct" then the architecture should be here, in the "correct" section.
#if defined(_M_X64) || defined(__x86_64__) || \
defined(__ARMEL__) || defined(_M_ARM) || defined(__arm__) || defined(__arm64__) || \
defined(__avr32__) || \
defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
defined(__riscv) || \
defined(__AARCH64EL__) || \
defined(nios2) || defined(__nios2) || defined(__nios2__)
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(__mc68000__) || \
defined(__pnacl__) || defined(__native_client__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
// Windows uses a 64bit wide floating point stack.
@@ -77,12 +118,6 @@
#error Target architecture was not detected as supported by Double-Conversion.
#endif
#if defined(__GNUC__)
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
#if defined(_WIN32) && !defined(__MINGW32__)
typedef signed char int8_t;
@@ -101,6 +136,8 @@ typedef unsigned __int64 uint64_t;
#endif
typedef uint16_t uc16;
// The following macro works on both 32 and 64-bit platforms.
// Usage: instead of writing 0x1234567890123456
// write UINT64_2PART_C(0x12345678,90123456);
@@ -119,8 +156,8 @@ typedef unsigned __int64 uint64_t;
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
#ifndef DC_DISALLOW_COPY_AND_ASSIGN
#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#endif
@@ -131,10 +168,10 @@ typedef unsigned __int64 uint64_t;
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
namespace double_conversion {
@@ -166,8 +203,8 @@ template <typename T>
class Vector {
public:
Vector() : start_(NULL), length_(0) {}
Vector(T* data, int length) : start_(data), length_(length) {
ASSERT(length == 0 || (length > 0 && data != NULL));
Vector(T* data, int len) : start_(data), length_(len) {
ASSERT(len == 0 || (len > 0 && data != NULL));
}
// Returns a vector using the same backing storage as this one,
@@ -209,8 +246,8 @@ class Vector {
// buffer bounds on all operations in debug mode.
class StringBuilder {
public:
StringBuilder(char* buffer, int size)
: buffer_(buffer, size), position_(0) { }
StringBuilder(char* buffer, int buffer_size)
: buffer_(buffer, buffer_size), position_(0) { }
~StringBuilder() { if (!is_finalized()) Finalize(); }
@@ -276,7 +313,7 @@ class StringBuilder {
bool is_finalized() const { return position_ < 0; }
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
// The type-based aliasing rule allows the compiler to assume that pointers of
@@ -307,8 +344,13 @@ template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
#if __cplusplus >= 201103L
static_assert(sizeof(Dest) == sizeof(Source),
"source and destination size mismatch");
#else
DOUBLE_CONVERSION_UNUSED
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
#endif
Dest dest;
memmove(&dest, &source, sizeof(dest));

View File

@@ -53,7 +53,7 @@ AnyTest::~AnyTest()
void AnyTest::testDefaultCtor()
{
const Any value;
assertTrue (value.empty());
assertTrue (0 == AnyCast<int>(&value));
assertTrue (value.type() == typeid(void));
@@ -64,7 +64,7 @@ void AnyTest::testConvertingCtor()
{
std::string text = "test message";
Any value = text;
assertTrue (!value.empty());
assertTrue (value.type() == typeid(std::string));
assertTrue (0 == AnyCast<int>(&value));
@@ -78,7 +78,7 @@ void AnyTest::testCopyCtor()
{
std::string text = "test message";
Any original = text, copy = original;
assertTrue (!copy.empty());
assertTrue (original.type() == copy.type());
assertTrue (AnyCast<std::string>(original) == AnyCast<std::string>(copy));
@@ -92,7 +92,7 @@ void AnyTest::testCopyAssign()
std::string text = "test message";
Any original = text, copy;
Any* assignResult = &(copy = original);
assertTrue (!copy.empty());
assertTrue (original.type() == copy.type());
assertTrue (AnyCast<std::string>(original) == AnyCast<std::string>(copy));
@@ -114,7 +114,7 @@ void AnyTest::testConvertingAssign()
std::string text = "test message";
Any value;
Any* assignResult = &(value = text);
assertTrue (!value.empty());
assertTrue (value.type() == typeid(std::string));
assertTrue (0 == AnyCast<int>(&value));
@@ -129,21 +129,23 @@ void AnyTest::testCastToReference()
{
Any a(137);
const Any b(a);
int& ra = AnyCast<int &>(a);
int const& ra_c = AnyCast<int const &>(a);
// NOTE: The following two AnyCasts will trigger the
// undefined behavior sanitizer.
int volatile& ra_v = AnyCast<int volatile &>(a);
int const volatile& ra_cv = AnyCast<int const volatile&>(a);
// cv references to same obj
assertTrue (&ra == &ra_c && &ra == &ra_v && &ra == &ra_cv);
int const & rb_c = AnyCast<int const &>(b);
int const volatile & rb_cv = AnyCast<int const volatile &>(b);
assertTrue (&rb_c == &rb_cv); // cv references to copied const obj
assertTrue (&ra != &rb_c); // copies hold different objects
++ra;
int incremented = AnyCast<int>(a);
assertTrue (incremented == 138); // increment by reference changes value
@@ -168,7 +170,7 @@ void AnyTest::testBadCast()
{
std::string text = "test message";
Any value = text;
try
{
AnyCast<const char *>(value);
@@ -184,7 +186,7 @@ void AnyTest::testSwap()
Any original = text, swapped;
std::string* originalPtr = AnyCast<std::string>(&original);
Any* swapResult = &original.swap(swapped);
assertTrue (original.empty());
assertTrue (!swapped.empty());
assertTrue (swapped.type() == typeid(std::string));
@@ -202,7 +204,7 @@ void AnyTest::testEmptyCopy()
const Any null;
Any copied = null, assigned;
assigned = null;
assertTrue (null.empty());
assertTrue (copied.empty());
assertTrue (assigned.empty());
@@ -261,7 +263,7 @@ void AnyTest::testVector()
assertTrue (tmp2.size() == 3);
const std::vector<int>& vecCRef = RefAnyCast<std::vector<int> >(a);
std::vector<int>& vecRef = RefAnyCast<std::vector<int> >(a);
assertTrue (vecRef[0] == 1);
assertTrue (vecRef[1] == 2);
assertTrue (vecRef[2] == 3);

View File

@@ -34,6 +34,7 @@ BasicEventTest::~BasicEventTest()
{
}
void BasicEventTest::testNoDelegate()
{
int tmp = 0;
@@ -66,12 +67,12 @@ void BasicEventTest::testNoDelegate()
Simple -= delegate(this, &BasicEventTest::onSimpleNoSender);
Simple.notify(this, tmp);
assertTrue (_count == 0);
ConstSimple += delegate(this, &BasicEventTest::onConstSimple);
ConstSimple -= delegate(this, &BasicEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
assertTrue (_count == 0);
//Note: passing &args will not work due to &
EventArgs* pArgs = &args;
Complex += delegate(this, &BasicEventTest::onComplex);
@@ -99,7 +100,7 @@ void BasicEventTest::testNoDelegate()
Simple += delegate(&BasicEventTest::onStaticSimple);
Simple += delegate(&BasicEventTest::onStaticSimple2);
Simple += delegate(&BasicEventTest::onStaticSimple3);
Simple.notify(this, tmp);
assertTrue (_count == 3);
Simple -= delegate(BasicEventTest::onStaticSimple);
@@ -112,6 +113,7 @@ void BasicEventTest::testNoDelegate()
Void -= delegate(BasicEventTest::onStaticVoid);
}
void BasicEventTest::testSingleDelegate()
{
int tmp = 0;
@@ -126,11 +128,11 @@ void BasicEventTest::testSingleDelegate()
Simple += delegate(this, &BasicEventTest::onSimple);
Simple.notify(this, tmp);
assertTrue (_count == 2);
ConstSimple += delegate(this, &BasicEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
assertTrue (_count == 3);
EventArgs* pArgs = &args;
Complex += delegate(this, &BasicEventTest::onComplex);
Complex.notify(this, pArgs);
@@ -151,13 +153,13 @@ void BasicEventTest::testSingleDelegate()
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
assertTrue (_count == 8);
}
void BasicEventTest::testDuplicateRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &BasicEventTest::onSimple);
@@ -174,7 +176,7 @@ void BasicEventTest::testNullMutex()
{
Poco::BasicEvent<int, NullMutex> ev;
int tmp = 0;
assertTrue (_count == 0);
ev += delegate(this, &BasicEventTest::onSimple);
@@ -191,7 +193,7 @@ void BasicEventTest::testDuplicateUnregister()
{
// duplicate unregister shouldn't give an error,
int tmp = 0;
assertTrue (_count == 0);
Simple -= delegate(this, &BasicEventTest::onSimple); // should work
@@ -211,10 +213,11 @@ void BasicEventTest::testDuplicateUnregister()
assertTrue (_count == 1);
}
void BasicEventTest::testDisabling()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &BasicEventTest::onSimple);
@@ -233,10 +236,11 @@ void BasicEventTest::testDisabling()
assertTrue (_count == 1);
}
void BasicEventTest::testExpire()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &BasicEventTest::onSimple, 500);
@@ -257,10 +261,11 @@ void BasicEventTest::testExpire()
assertTrue (_count == 4);
}
void BasicEventTest::testExpireReRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &BasicEventTest::onSimple, 500);
@@ -279,6 +284,7 @@ void BasicEventTest::testExpireReRegister()
assertTrue (_count == 3);
}
void BasicEventTest::testReturnParams()
{
DummyDelegate o1;
@@ -289,6 +295,7 @@ void BasicEventTest::testReturnParams()
assertTrue (tmp == 1);
}
void BasicEventTest::testOverwriteDelegate()
{
DummyDelegate o1;
@@ -300,32 +307,34 @@ void BasicEventTest::testOverwriteDelegate()
assertTrue (tmp == 2);
}
void BasicEventTest::testAsyncNotify()
{
Poco::BasicEvent<int>* pSimple= new Poco::BasicEvent<int>();
(*pSimple) += delegate(this, &BasicEventTest::onAsync);
Poco::BasicEvent<int> simple;
simple += delegate(this, &BasicEventTest::onAsync);
assertTrue (_count == 0);
int tmp = 0;
Poco::ActiveResult<int>retArg = pSimple->notifyAsync(this, tmp);
delete pSimple; // must work even when the event got deleted!
pSimple = NULL;
Poco::ActiveResult<int>retArg = simple.notifyAsync(this, tmp);
assertTrue (_count == 0);
retArg.wait();
assertTrue (retArg.data() == tmp);
assertTrue (_count == LARGEINC);
}
void BasicEventTest::onStaticVoid(const void* pSender)
{
BasicEventTest* p = const_cast<BasicEventTest*>(reinterpret_cast<const BasicEventTest*>(pSender));
p->_count++;
}
void BasicEventTest::onVoid(const void* pSender)
{
_count++;
}
void BasicEventTest::onSimpleNoSender(int& i)
{
_count++;
@@ -362,47 +371,55 @@ void BasicEventTest::onSimpleOther(const void* pSender, int& i)
_count+=100;
}
void BasicEventTest::onConstSimple(const void* pSender, const int& i)
{
_count++;
}
void BasicEventTest::onComplex(const void* pSender, Poco::EventArgs* & i)
{
_count++;
}
void BasicEventTest::onComplex2(const void* pSender, Poco::EventArgs & i)
{
_count++;
}
void BasicEventTest::onConstComplex(const void* pSender, const Poco::EventArgs*& i)
{
_count++;
}
void BasicEventTest::onConst2Complex(const void* pSender, const Poco::EventArgs * const & i)
{
_count++;
}
void BasicEventTest::onAsync(const void* pSender, int& i)
{
Poco::Thread::sleep(700);
_count += LARGEINC ;
}
int BasicEventTest::getCount() const
{
return _count;
}
void BasicEventTest::setUp()
{
_count = 0;
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// because tests are only created once, only setup is called before
// each test run
Void.clear();
Simple.clear();

View File

@@ -56,7 +56,7 @@ namespace
_counter(counter)
{
}
void run()
{
for (int i = 0; i < 100000; ++i)
@@ -67,7 +67,7 @@ namespace
--_counter;
}
}
private:
AtomicCounter& _counter;
};
@@ -93,7 +93,7 @@ int Parent::i = 0;
struct Medium : public Parent
{
};
@@ -142,7 +142,7 @@ void CoreTest::testFixedLength()
assertTrue (sizeof(Poco::UInt64) == 8);
#endif
assertTrue (sizeof(Poco::IntPtr) == sizeof(void*));
assertTrue (sizeof(Poco::UIntPtr) == sizeof(void*));
assertTrue (sizeof(Poco::UIntPtr) == sizeof(void*));
}
@@ -151,7 +151,7 @@ void CoreTest::testBugcheck()
#if ENABLE_BUGCHECK_TEST
try
{
Bugcheck::assertion("test", __FILE__, __LINE__);
Bugcheck::assertion("test", __FILE__, __LINE__);
failmsg("must throw exception");
}
catch (Exception&)
@@ -160,7 +160,7 @@ void CoreTest::testBugcheck()
try
{
Bugcheck::nullPointer("test", __FILE__, __LINE__);
Bugcheck::nullPointer("test", __FILE__, __LINE__);
failmsg("must throw exception");
}
catch (Exception&)
@@ -169,7 +169,7 @@ void CoreTest::testBugcheck()
try
{
Bugcheck::bugcheck("test", __FILE__, __LINE__);
Bugcheck::bugcheck("test", __FILE__, __LINE__);
failmsg("must throw exception");
}
catch (Exception&)
@@ -181,7 +181,7 @@ void CoreTest::testBugcheck()
void CoreTest::testEnvironment()
{
#if !defined(_WIN32_WCE)
#if !defined(_WIN32_WCE)
Environment::set("FOO", "BAR");
assertTrue (Environment::has("FOO"));
assertTrue (Environment::get("FOO") == "BAR");
@@ -194,7 +194,7 @@ void CoreTest::testEnvironment()
catch (Exception&)
{
}
std::cout << "OS Name: " << Environment::osName() << std::endl;
std::cout << "OS Display Name: " << Environment::osDisplayName() << std::endl;
std::cout << "OS Version: " << Environment::osVersion() << std::endl;
@@ -321,7 +321,7 @@ void CoreTest::testFIFOBufferEOFAndError()
typedef FIFOBuffer::Type T;
FIFOBuffer f(20, true);
assertTrue (f.isEmpty());
assertTrue (!f.isFull());
@@ -384,7 +384,7 @@ void CoreTest::testFIFOBufferEOFAndError()
assertTrue (5 == f.used());
f.setError();
assertTrue (0 == f.write(b));
try
{
f.copy(b.begin(), 5);
@@ -398,7 +398,7 @@ void CoreTest::testFIFOBufferEOFAndError()
fail ("must throw InvalidAccessException");
}
catch (InvalidAccessException&) { }
assertTrue (1 == _notToWritable);
assertTrue (2 == _writableToNot);
assertTrue (2 == _notToReadable);
@@ -427,7 +427,7 @@ void CoreTest::testFIFOBufferChar()
typedef FIFOBuffer::Type T;
FIFOBuffer f(20, true);
assertTrue (f.isEmpty());
assertTrue (!f.isFull());
@@ -743,7 +743,7 @@ void CoreTest::testFIFOBufferChar()
assertTrue (10 == f.size());
assertTrue (10 == f.used());
assertTrue (0 == f.available());
assertTrue (f[0] == '2');
assertTrue (f[1] == '3');
assertTrue (f[2] == '4');
@@ -906,41 +906,41 @@ void CoreTest::testFIFOBufferInt()
void CoreTest::testAtomicCounter()
{
AtomicCounter ac;
assertTrue (ac.value() == 0);
assertTrue (ac++ == 0);
assertTrue (ac-- == 1);
assertTrue (++ac == 1);
assertTrue (--ac == 0);
ac = 2;
assertTrue (ac.value() == 2);
ac = 0;
assertTrue (ac.value() == 0);
AtomicCounter ac2(2);
assertTrue (ac2.value() == 2);
ACTRunnable act(ac);
Thread t1;
Thread t2;
Thread t3;
Thread t4;
Thread t5;
t1.start(act);
t2.start(act);
t3.start(act);
t4.start(act);
t5.start(act);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
assertTrue (ac.value() == 0);
}
@@ -977,14 +977,14 @@ void CoreTest::testNullable()
Nullable<int> n1;
assertTrue (n1.isNull());
assertTrue (n1.value(42) == 42);
assertTrue (n1.isNull());
assertTrue (!(0 == n1));
assertTrue (0 != n1);
assertTrue (!(n1 == 0));
assertTrue (n1 != 0);
try
{
int POCO_UNUSED tmp = n1.value();
@@ -993,25 +993,25 @@ void CoreTest::testNullable()
catch (Poco::NullValueException&)
{
}
n1 = 1;
assertTrue (!n1.isNull());
assertTrue (n1.value() == 1);
Nullable<int> n2(42);
assertTrue (!n2.isNull());
assertTrue (n2.value() == 42);
assertTrue (n2.value(99) == 42);
assertTrue (!(0 == n2));
assertTrue (0 != n2);
assertTrue (!(n2 == 0));
assertTrue (n2 != 0);
n1 = n2;
assertTrue (!n1.isNull());
assertTrue (n1.value() == 42);
std::ostringstream str;
str << n1;
assertTrue (str.str() == "42");
@@ -1034,7 +1034,7 @@ void CoreTest::testNullable()
assertTrue (n2 != n1);
assertTrue (n1 > n2);
NullType nd;
NullType nd{};
assertTrue (n1 != nd);
assertTrue (nd != n1);
n1.clear();
@@ -1049,7 +1049,7 @@ void CoreTest::testAscii()
assertTrue (!Ascii::isAscii(-1));
assertTrue (!Ascii::isAscii(128));
assertTrue (!Ascii::isAscii(222));
assertTrue (Ascii::isSpace(' '));
assertTrue (Ascii::isSpace('\t'));
assertTrue (Ascii::isSpace('\r'));
@@ -1057,7 +1057,7 @@ void CoreTest::testAscii()
assertTrue (!Ascii::isSpace('A'));
assertTrue (!Ascii::isSpace(-1));
assertTrue (!Ascii::isSpace(222));
assertTrue (Ascii::isDigit('0'));
assertTrue (Ascii::isDigit('1'));
assertTrue (Ascii::isDigit('2'));
@@ -1069,7 +1069,7 @@ void CoreTest::testAscii()
assertTrue (Ascii::isDigit('8'));
assertTrue (Ascii::isDigit('9'));
assertTrue (!Ascii::isDigit('a'));
assertTrue (Ascii::isHexDigit('0'));
assertTrue (Ascii::isHexDigit('1'));
assertTrue (Ascii::isHexDigit('2'));
@@ -1097,21 +1097,21 @@ void CoreTest::testAscii()
assertTrue (Ascii::isPunct('.'));
assertTrue (Ascii::isPunct(','));
assertTrue (!Ascii::isPunct('A'));
assertTrue (Ascii::isAlpha('a'));
assertTrue (Ascii::isAlpha('Z'));
assertTrue (!Ascii::isAlpha('0'));
assertTrue (Ascii::isLower('a'));
assertTrue (!Ascii::isLower('A'));
assertTrue (Ascii::isUpper('A'));
assertTrue (!Ascii::isUpper('a'));
assertTrue (Ascii::toLower('A') == 'a');
assertTrue (Ascii::toLower('z') == 'z');
assertTrue (Ascii::toLower('0') == '0');
assertTrue (Ascii::toUpper('a') == 'A');
assertTrue (Ascii::toUpper('0') == '0');
assertTrue (Ascii::toUpper('Z') == 'Z');

View File

@@ -8,6 +8,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "DateTimeTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"

View File

@@ -33,6 +33,7 @@ FIFOEventTest::~FIFOEventTest()
{
}
void FIFOEventTest::testNoDelegate()
{
int tmp = 0;
@@ -54,12 +55,12 @@ void FIFOEventTest::testNoDelegate()
Simple -= delegate(this, &FIFOEventTest::onSimple);
Simple.notify(this, tmp);
assertTrue (_count == 0);
ConstSimple += delegate(this, &FIFOEventTest::onConstSimple);
ConstSimple -= delegate(this, &FIFOEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
assertTrue (_count == 0);
//Note: passing &args will not work due to &
EventArgs* pArgs = &args;
Complex += delegate(this, &FIFOEventTest::onComplex);
@@ -84,6 +85,7 @@ void FIFOEventTest::testNoDelegate()
assertTrue (_count == 0);
}
void FIFOEventTest::testSingleDelegate()
{
int tmp = 0;
@@ -98,11 +100,11 @@ void FIFOEventTest::testSingleDelegate()
Simple += delegate(this, &FIFOEventTest::onSimple);
Simple.notify(this, tmp);
assertTrue (_count == 2);
ConstSimple += delegate(this, &FIFOEventTest::onConstSimple);
ConstSimple.notify(this, tmp);
assertTrue (_count == 3);
EventArgs* pArgs = &args;
Complex += delegate(this, &FIFOEventTest::onComplex);
Complex.notify(this, pArgs);
@@ -123,13 +125,13 @@ void FIFOEventTest::testSingleDelegate()
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
assertTrue (_count == 8);
}
void FIFOEventTest::testDuplicateRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &FIFOEventTest::onSimple);
@@ -141,11 +143,12 @@ void FIFOEventTest::testDuplicateRegister()
assertTrue (_count == 3);
}
void FIFOEventTest::testDuplicateUnregister()
{
// duplicate unregister shouldn't give an error,
int tmp = 0;
assertTrue (_count == 0);
Simple -= delegate(this, &FIFOEventTest::onSimple); // should work
@@ -169,7 +172,7 @@ void FIFOEventTest::testDuplicateUnregister()
void FIFOEventTest::testDisabling()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &FIFOEventTest::onSimple);
@@ -188,6 +191,7 @@ void FIFOEventTest::testDisabling()
assertTrue (_count == 1);
}
void FIFOEventTest::testFIFOOrder()
{
DummyDelegate o1;
@@ -203,7 +207,7 @@ void FIFOEventTest::testFIFOOrder()
Simple -= delegate(&o1, &DummyDelegate::onSimple);
Simple -= delegate(&o2, &DummyDelegate::onSimple2);
// now try with the wrong order
Simple += delegate(&o2, &DummyDelegate::onSimple2);
Simple += delegate(&o1, &DummyDelegate::onSimple);
@@ -219,6 +223,7 @@ void FIFOEventTest::testFIFOOrder()
}
}
void FIFOEventTest::testFIFOOrderExpire()
{
// expire must not break order!
@@ -238,7 +243,7 @@ void FIFOEventTest::testFIFOOrderExpire()
Simple -= delegate(&o2, &DummyDelegate::onSimple2);
Simple.notify(this, tmp);
assertTrue (tmp == 2);
// now start mixing of expire and non expire
tmp = 0;
Simple += delegate(&o1, &DummyDelegate::onSimple);
@@ -255,7 +260,7 @@ void FIFOEventTest::testFIFOOrderExpire()
// now try with the wrong order
Simple += delegate(&o2, &DummyDelegate::onSimple2, 5000);
Simple += delegate(&o1, &DummyDelegate::onSimple);
try
{
tmp = 0;
@@ -264,15 +269,14 @@ void FIFOEventTest::testFIFOOrderExpire()
}
catch (Poco::InvalidArgumentException&)
{
}
}
void FIFOEventTest::testExpire()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &FIFOEventTest::onSimple, 500);
@@ -287,7 +291,7 @@ void FIFOEventTest::testExpire()
void FIFOEventTest::testExpireReRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += delegate(this, &FIFOEventTest::onSimple, 500);
@@ -317,6 +321,7 @@ void FIFOEventTest::testReturnParams()
assertTrue (tmp == 1);
}
void FIFOEventTest::testOverwriteDelegate()
{
DummyDelegate o1;
@@ -328,77 +333,87 @@ void FIFOEventTest::testOverwriteDelegate()
assertTrue (tmp == 2);
}
void FIFOEventTest::testAsyncNotify()
{
Poco::FIFOEvent<int >* pSimple= new Poco::FIFOEvent<int>();
(*pSimple) += delegate(this, &FIFOEventTest::onAsync);
Poco::FIFOEvent<int> simple;
simple += delegate(this, &FIFOEventTest::onAsync);
assertTrue (_count == 0);
int tmp = 0;
Poco::ActiveResult<int>retArg = pSimple->notifyAsync(this, tmp);
delete pSimple; // must work even when the event got deleted!
pSimple = NULL;
Poco::ActiveResult<int>retArg = simple.notifyAsync(this, tmp);
assertTrue (_count == 0);
retArg.wait();
assertTrue (retArg.data() == tmp);
assertTrue (_count == LARGEINC);
}
void FIFOEventTest::onVoid(const void* pSender)
{
_count++;
}
void FIFOEventTest::onSimple(const void* pSender, int& i)
{
_count++;
}
void FIFOEventTest::onSimpleOther(const void* pSender, int& i)
{
_count+=100;
}
void FIFOEventTest::onConstSimple(const void* pSender, const int& i)
{
_count++;
}
void FIFOEventTest::onComplex(const void* pSender, Poco::EventArgs* & i)
{
_count++;
}
void FIFOEventTest::onComplex2(const void* pSender, Poco::EventArgs & i)
{
_count++;
}
void FIFOEventTest::onConstComplex(const void* pSender, const Poco::EventArgs*& i)
{
_count++;
}
void FIFOEventTest::onConst2Complex(const void* pSender, const Poco::EventArgs * const & i)
{
_count++;
}
void FIFOEventTest::onAsync(const void* pSender, int& i)
{
Poco::Thread::sleep(700);
_count += LARGEINC ;
}
int FIFOEventTest::getCount() const
{
return _count;
}
void FIFOEventTest::setUp()
{
_count = 0;
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// because tests are only created once, only setup is called before
// each test run
Void.clear();
Simple.clear();

View File

@@ -526,7 +526,7 @@ void FileChannelTest::testWrongPurgeOption()
{
pChannel->setProperty(FileChannel::PROP_PURGEAGE, "peace");
fail("must fail");
} catch (InvalidArgumentException)
} catch (InvalidArgumentException&)
{
assertTrue (pChannel->getProperty(FileChannel::PROP_PURGEAGE) == "5 seconds");
}
@@ -535,7 +535,7 @@ void FileChannelTest::testWrongPurgeOption()
{
pChannel->setProperty(FileChannel::PROP_PURGECOUNT, "peace");
fail("must fail");
} catch (InvalidArgumentException)
} catch (InvalidArgumentException&)
{
assertTrue (pChannel->getProperty(FileChannel::PROP_PURGEAGE) == "5 seconds");
}

View File

@@ -221,6 +221,29 @@ void LRUCacheTest::testUpdate()
}
void LRUCacheTest::testForEach()
{
LRUCache<int, int> aCache(3);
std::map<int, int> values;
aCache.add(1, 100);
aCache.add(2, 200);
aCache.add(3, 300);
aCache.forEach(
[&values](int key, int value)
{
values[key] = value;
}
);
assertEquals (values.size(), 3);
assertEquals (values[1], 100);
assertEquals (values[2], 200);
assertEquals (values[3], 300);
}
void LRUCacheTest::onUpdate(const void* pSender, const Poco::KeyValueArgs<int, int>& args)
{
++updateCnt;
@@ -260,6 +283,7 @@ CppUnit::Test* LRUCacheTest::suite()
CppUnit_addTest(pSuite, LRUCacheTest, testCacheSizeN);
CppUnit_addTest(pSuite, LRUCacheTest, testDuplicateAdd);
CppUnit_addTest(pSuite, LRUCacheTest, testUpdate);
CppUnit_addTest(pSuite, LRUCacheTest, testForEach);
return pSuite;
}

View File

@@ -31,6 +31,7 @@ public:
void testCacheSizeN();
void testDuplicateAdd();
void testUpdate();
void testForEach();
void setUp();
void tearDown();

View File

@@ -8,6 +8,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "LocalDateTimeTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
@@ -24,6 +29,7 @@
#include "wce_time.h"
#endif
using Poco::LocalDateTime;
using Poco::DateTime;
using Poco::Timestamp;

View File

@@ -33,7 +33,7 @@ namespace
public:
void run()
{
testEvent.wait();
_timestamp.update();
}
@@ -66,11 +66,11 @@ void NamedEventTest::testNamedEvent()
thr1.start(te);
Timestamp now;
Thread::sleep(2000);
try
try
{
testEvent.set();
}
catch(Poco::NotImplementedException e)
catch(Poco::NotImplementedException& e)
{
#if POCO_OS != POCO_OS_ANDROID
throw e;
@@ -84,11 +84,11 @@ void NamedEventTest::testNamedEvent()
thr2.start(te);
now.update();
Thread::sleep(2000);
try
try
{
testEvent.set();
}
catch(Poco::NotImplementedException e)
catch(Poco::NotImplementedException& e)
{
#if POCO_OS != POCO_OS_ANDROID
throw e;

View File

@@ -33,7 +33,7 @@ namespace
public:
void run()
{
testMutex.lock();
_timestamp.update();
testMutex.unlock();
@@ -54,7 +54,7 @@ namespace
TestTryLock(): _locked(false)
{
}
void run()
{
if (testMutex.tryLock())
@@ -87,7 +87,7 @@ NamedMutexTest::~NamedMutexTest()
void NamedMutexTest::testLock()
{
try
try
{
testMutex.lock();
Thread thr;
@@ -99,7 +99,7 @@ void NamedMutexTest::testLock()
thr.join();
assertTrue (tl.timestamp() > now);
}
catch(Poco::NotImplementedException e)
catch(Poco::NotImplementedException& e)
{
#if POCO_OS != POCO_OS_ANDROID
throw e;
@@ -117,7 +117,7 @@ void NamedMutexTest::testTryLock()
#if POCO_OS != POCO_OS_ANDROID
assertTrue (ttl1.locked());
#endif
try
try
{
testMutex.lock();
Thread thr2;
@@ -127,7 +127,7 @@ void NamedMutexTest::testTryLock()
testMutex.unlock();
assertTrue (!ttl2.locked());
}
catch(Poco::NotImplementedException e)
catch(Poco::NotImplementedException& e)
{
#if POCO_OS != POCO_OS_ANDROID
throw e;

View File

@@ -13,6 +13,7 @@
#include "CppUnit/TestSuite.h"
#include "Poco/ObjectPool.h"
#include "Poco/Exception.h"
#include "Poco/Thread.h"
using Poco::ObjectPool;
@@ -30,18 +31,18 @@ ObjectPoolTest::~ObjectPoolTest()
void ObjectPoolTest::testObjectPool()
{
ObjectPool<std::string, Poco::SharedPtr<std::string> > pool(3, 4);
ObjectPool<std::string, Poco::SharedPtr<std::string>> pool(3, 4);
assertTrue (pool.capacity() == 3);
assertTrue (pool.peakCapacity() == 4);
assertTrue (pool.size() == 0);
assertTrue (pool.available() == 4);
Poco::SharedPtr<std::string> pStr1 = pool.borrowObject();
pStr1->assign("first");
assertTrue (pool.size() == 1);
assertTrue (pool.available() == 3);
Poco::SharedPtr<std::string> pStr2 = pool.borrowObject();
pStr2->assign("second");
assertTrue (pool.size() == 2);
@@ -51,19 +52,19 @@ void ObjectPoolTest::testObjectPool()
pStr3->assign("third");
assertTrue (pool.size() == 3);
assertTrue (pool.available() == 1);
Poco::SharedPtr<std::string> pStr4 = pool.borrowObject();
pStr4->assign("fourth");
assertTrue (pool.size() == 4);
assertTrue (pool.available() == 0);
Poco::SharedPtr<std::string> pStr5 = pool.borrowObject();
assertTrue (pStr5.isNull());
pool.returnObject(pStr4);
assertTrue (pool.size() == 4);
assertTrue (pool.available() == 1);
pool.returnObject(pStr3);
assertTrue (pool.size() == 4);
assertTrue (pool.available() == 2);
@@ -75,10 +76,10 @@ void ObjectPoolTest::testObjectPool()
pool.returnObject(pStr3);
pool.returnObject(pStr2);
pool.returnObject(pStr1);
assertTrue (pool.size() == 3);
assertTrue (pool.available() == 4);
pStr1 = pool.borrowObject();
assertTrue (*pStr1 == "second");
assertTrue (pool.available() == 3);
@@ -88,6 +89,27 @@ void ObjectPoolTest::testObjectPool()
}
void ObjectPoolTest::testObjectPoolWaitOnBorrowObject()
{
ObjectPool<std::string, Poco::SharedPtr<std::string>> pool(1, 1);
Poco::SharedPtr<std::string> objectToReturnDuringBorrow = pool.borrowObject();
Poco::Thread threadToReturnObject;
threadToReturnObject.startFunc(
[&pool, &objectToReturnDuringBorrow]()
{
pool.returnObject(objectToReturnDuringBorrow);
}
);
Poco::SharedPtr<std::string> object = pool.borrowObject(1000);
threadToReturnObject.join();
assertFalse(object.isNull());
}
void ObjectPoolTest::setUp()
{
}
@@ -103,6 +125,7 @@ CppUnit::Test* ObjectPoolTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ObjectPoolTest");
CppUnit_addTest(pSuite, ObjectPoolTest, testObjectPool);
CppUnit_addTest(pSuite, ObjectPoolTest, testObjectPoolWaitOnBorrowObject);
return pSuite;
}

View File

@@ -25,6 +25,7 @@ public:
~ObjectPoolTest();
void testObjectPool();
void testObjectPoolWaitOnBorrowObject();
void setUp();
void tearDown();

View File

@@ -907,7 +907,7 @@ void OrderedContainersTest::testHeterogeneousLookups()
map.at(addr_unknown);
fail("must throw");
}
catch (std::out_of_range) {}
catch (std::out_of_range&) {}
assertTrue(map.find(addr1) != map.end());
assertEquals(*map.find(addr1)->first, 1);

View File

@@ -30,9 +30,6 @@
using Poco::Path;
using Poco::PathSyntaxException;
using Poco::Environment;
using std::clog;
using std::cout;
using std::endl;
PathTest::PathTest(const std::string& name): CppUnit::TestCase(name)
@@ -1239,7 +1236,6 @@ void PathTest::testParseVMS4()
assertTrue (p[0] == "foo");
assertTrue (!p.isDirectory());
assertTrue (p.isFile());
cout << "p.toString(Path::PATH_VMS)=" << p.toString(Path::PATH_VMS) << endl;
assertTrue (p.toString(Path::PATH_VMS) == "[foo]bar.txt;5");
assertTrue (p.version() == "5");
@@ -1301,7 +1297,6 @@ void PathTest::testParseGuess()
assertTrue (p.getDevice() == "foo");
assertTrue (!p.isDirectory());
assertTrue (p.isFile());
cout << "p.toString(Path::PATH_VMS)=" << p.toString(Path::PATH_VMS) << endl;
assertTrue (p.toString(Path::PATH_VMS) == "foo:bar.txt;5");
assertTrue (p.version() == "5");

View File

@@ -42,6 +42,7 @@ void PatternFormatterTest::testPatternFormatter()
msg.setThread("TestThread");
msg.setPriority(Message::PRIO_ERROR);
msg.setTime(DateTime(2005, 1, 1, 14, 30, 15, 500).timestamp());
msg.setSourceFile(__FILE__);
msg["testParam"] = "Test Parameter";
std::string result;
@@ -91,6 +92,17 @@ void PatternFormatterTest::testPatternFormatter()
fmt.setProperty("pattern", "start %v[8] end");
fmt.format(msg, result);
assertTrue (result == "start stSource end");
result.clear();
fmt.setProperty("pattern", "%O");
fmt.format(msg, result);
assertTrue (result == "PatternFormatterTest.cpp");
result.clear();
fmt.setProperty("priorityNames", "FATAL,CRITICAL,SPECIAL_ERROR_NAME,WARN,NOTICE,INFO,DEBUG,TRACE");
fmt.setProperty("pattern", "%p");
fmt.format(msg, result);
assertTrue (result == "SPECIAL_ERROR_NAME");
}

View File

@@ -33,6 +33,7 @@ PriorityEventTest::~PriorityEventTest()
{
}
void PriorityEventTest::testNoDelegate()
{
int tmp = 0;
@@ -59,12 +60,12 @@ void PriorityEventTest::testNoDelegate()
Simple -= priorityDelegate(this, &PriorityEventTest::onSimpleNoSender, 0);
Simple.notify(this, tmp);
assertTrue (_count == 0);
ConstSimple += priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
ConstSimple -= priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
ConstSimple.notify(this, tmp);
assertTrue (_count == 0);
//Note: passing &args will not work due to &
EventArgs* pArgs = &args;
Complex += priorityDelegate(this, &PriorityEventTest::onComplex, 0);
@@ -93,7 +94,7 @@ void PriorityEventTest::testNoDelegate()
Simple += priorityDelegate(&PriorityEventTest::onStaticSimple, 1);
Simple += priorityDelegate(&PriorityEventTest::onStaticSimple2, 2);
Simple += priorityDelegate(&PriorityEventTest::onStaticSimple3, 3);
Simple.notify(this, tmp);
assertTrue (_count == 4);
Simple -= priorityDelegate(PriorityEventTest::onStaticSimple, 0);
@@ -108,6 +109,7 @@ void PriorityEventTest::testNoDelegate()
Void -= priorityDelegate(PriorityEventTest::onStaticVoid, 0);
}
void PriorityEventTest::testSingleDelegate()
{
int tmp = 0;
@@ -126,12 +128,12 @@ void PriorityEventTest::testSingleDelegate()
Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 3);
Simple.notify(this, tmp);
assertTrue (_count == 2);
ConstSimple += priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
ConstSimple -= priorityDelegate(this, &PriorityEventTest::onConstSimple, 3);
ConstSimple.notify(this, tmp);
assertTrue (_count == 3);
EventArgs* pArgs = &args;
Complex += priorityDelegate(this, &PriorityEventTest::onComplex, 0);
Complex -= priorityDelegate(this, &PriorityEventTest::onComplex, 3);
@@ -156,13 +158,13 @@ void PriorityEventTest::testSingleDelegate()
// check if 2nd notify also works
Const2Complex.notify(this, pArgs);
assertTrue (_count == 8);
}
void PriorityEventTest::testDuplicateRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
@@ -181,11 +183,12 @@ void PriorityEventTest::testDuplicateRegister()
assertTrue (_count == 5 + LARGEINC);
}
void PriorityEventTest::testDuplicateUnregister()
{
// duplicate unregister shouldn't give an error,
int tmp = 0;
assertTrue (_count == 0);
Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0); // should work
@@ -209,7 +212,7 @@ void PriorityEventTest::testDuplicateUnregister()
void PriorityEventTest::testDisabling()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
@@ -228,6 +231,7 @@ void PriorityEventTest::testDisabling()
assertTrue (_count == 1);
}
void PriorityEventTest::testPriorityOrder()
{
DummyDelegate o1;
@@ -244,7 +248,7 @@ void PriorityEventTest::testPriorityOrder()
Simple -= PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 0);
Simple -= PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 1);
// now try with the wrong order
Simple += PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 0);
Simple += PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 1);
@@ -263,6 +267,7 @@ void PriorityEventTest::testPriorityOrder()
Simple -= PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 1);
}
void PriorityEventTest::testPriorityOrderExpire()
{
// expire must not break order!
@@ -282,12 +287,12 @@ void PriorityEventTest::testPriorityOrderExpire()
Simple -= priorityDelegate(&o2, &DummyDelegate::onSimple2, 1);
Simple.notify(this, tmp);
assertTrue (tmp == 2);
// now start mixing of expire and non expire
tmp = 0;
Simple += priorityDelegate(&o2, &DummyDelegate::onSimple2, 1, 500000);
Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 0);
Simple.notify(this, tmp);
assertTrue (tmp == 2);
@@ -313,13 +318,13 @@ void PriorityEventTest::testPriorityOrderExpire()
Simple -= priorityDelegate(&o2, &DummyDelegate::onSimple2, 0, 500000);
Simple -= priorityDelegate(&o1, &DummyDelegate::onSimple, 1);
}
void PriorityEventTest::testExpire()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 1, 500);
@@ -344,7 +349,7 @@ void PriorityEventTest::testExpire()
void PriorityEventTest::testExpireReRegister()
{
int tmp = 0;
assertTrue (_count == 0);
Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 1, 500);
@@ -374,6 +379,7 @@ void PriorityEventTest::testReturnParams()
assertTrue (tmp == 1);
}
void PriorityEventTest::testOverwriteDelegate()
{
DummyDelegate o1;
@@ -385,32 +391,33 @@ void PriorityEventTest::testOverwriteDelegate()
assertTrue (tmp == 2);
}
void PriorityEventTest::testAsyncNotify()
{
Poco::PriorityEvent<int >* pSimple= new Poco::PriorityEvent<int>();
(*pSimple) += priorityDelegate(this, &PriorityEventTest::onAsync, 0);
Poco::PriorityEvent<int> simple;
simple += priorityDelegate(this, &PriorityEventTest::onAsync, 0);
assertTrue (_count == 0);
int tmp = 0;
Poco::ActiveResult<int>retArg = pSimple->notifyAsync(this, tmp);
delete pSimple; // must work even when the event got deleted!
pSimple = NULL;
Poco::ActiveResult<int>retArg = simple.notifyAsync(this, tmp);
assertTrue (_count == 0);
retArg.wait();
assertTrue (retArg.data() == tmp);
assertTrue (_count == LARGEINC);
}
void PriorityEventTest::onStaticVoid(const void* pSender)
{
PriorityEventTest* p = const_cast<PriorityEventTest*>(reinterpret_cast<const PriorityEventTest*>(pSender));
p->_count++;
}
void PriorityEventTest::onVoid(const void* pSender){
_count++;
}
void PriorityEventTest::onStaticSimple(const void* pSender, int& i)
{
PriorityEventTest* p = const_cast<PriorityEventTest*>(reinterpret_cast<const PriorityEventTest*>(pSender));
@@ -441,52 +448,61 @@ void PriorityEventTest::onSimple(const void* pSender, int& i)
_count++;
}
void PriorityEventTest::onSimpleOther(const void* pSender, int& i)
{
_count += LARGEINC ;
}
void PriorityEventTest::onConstSimple(const void* pSender, const int& i)
{
_count++;
}
void PriorityEventTest::onComplex(const void* pSender, Poco::EventArgs* & i)
{
_count++;
}
void PriorityEventTest::onComplex2(const void* pSender, Poco::EventArgs & i)
{
_count++;
}
void PriorityEventTest::onConstComplex(const void* pSender, const Poco::EventArgs*& i)
{
_count++;
}
void PriorityEventTest::onConst2Complex(const void* pSender, const Poco::EventArgs * const & i)
{
_count++;
}
void PriorityEventTest::onAsync(const void* pSender, int& i)
{
Poco::Thread::sleep(700);
_count += LARGEINC ;
}
int PriorityEventTest::getCount() const
{
return _count;
}
void PriorityEventTest::setUp()
{
_count = 0;
// must clear events, otherwise repeating test executions will fail
// because tests are only created once, only setup is called before
// because tests are only created once, only setup is called before
// each test run
Void.clear();
Simple.clear();

View File

@@ -8,6 +8,11 @@
//
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "StringTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
@@ -89,8 +94,12 @@ void StringTest::testTrimLeft()
std::string s = " abc ";
assertTrue (trimLeft(s) == "abc ");
{
std::string s = " ab c ";
assertTrue (trimLeft(s) == "ab c ");
std::string s = " ab c ";
assertTrue (trimLeft(s) == "ab c ");
}
{
std::string s;
assertTrue (trimLeft(s) == "");
}
}
@@ -109,6 +118,10 @@ void StringTest::testTrimLeftInPlace()
std::string s = " ab c ";
assertTrue (trimLeftInPlace(s) == "ab c ");
}
{
std::string s;
assertTrue (trimLeftInPlace(s) == "");
}
}
@@ -126,6 +139,10 @@ void StringTest::testTrimRight()
std::string s = " ab c ";
assertTrue (trimRight(s) == " ab c");
}
{
std::string s;
assertTrue (trimRight(s) == "");
}
}
@@ -143,6 +160,10 @@ void StringTest::testTrimRightInPlace()
std::string s = " ab c ";
assertTrue (trimRightInPlace(s) == " ab c");
}
{
std::string s;
assertTrue (trimRightInPlace(s) == "");
}
}
@@ -160,6 +181,10 @@ void StringTest::testTrim()
std::string s = " ab c ";
assertTrue (trim(s) == "ab c");
}
{
std::string s;
assertTrue (trim(s) == "");
}
}
@@ -177,6 +202,10 @@ void StringTest::testTrimInPlace()
std::string s = " ab c ";
assertTrue (trimInPlace(s) == "ab c");
}
{
std::string s;
assertTrue (trimInPlace(s) == "");
}
}
@@ -783,6 +812,7 @@ void StringTest::testNumericStringPadding()
{
std::string str;
assertTrue (floatToStr(str, 0.999f, 2, 4) == "1.00");
assertTrue (floatToStr(str, 0.999f, 2, 4, '.', ',') == "1,00");
assertTrue (floatToStr(str, 0.945f, 2, 4) == "0.95");
assertTrue (floatToStr(str, 0.944f, 2, 4) == "0.94");
assertTrue (floatToStr(str, 12.45f, 2, 5) == "12.45");
@@ -800,6 +830,7 @@ void StringTest::testNumericStringPadding()
assertTrue (doubleToStr(str, 12.45, 2, 6) == " 12.45");
assertTrue (doubleToStr(str, 12.455, 3, 7) == " 12.455");
assertTrue (doubleToStr(str, 12.455, 2, 6) == " 12.46");
assertTrue (doubleToStr(str, 12345.678, 3, 6, '.', ',') == "12.345,678");
assertTrue (doubleToStr(str, 1.23556E-16, 2, 6) == "1.24e-16");
}
@@ -1378,7 +1409,6 @@ void StringTest::testJSONString()
{
assertTrue (toJSON("\\", false) == "\\\\");
assertTrue (toJSON("\"", false) == "\\\"");
assertTrue (toJSON("/", false) == "\\/");
assertTrue (toJSON("\a", false) == "\\u0007");
assertTrue (toJSON("\b", false) == "\\b");
assertTrue (toJSON("\f", false) == "\\f");
@@ -1395,7 +1425,7 @@ void StringTest::testJSONString()
std::string str = "\"foo\\\\\"";
assertTrue (toJSON("foo\\") == str);
assertTrue (toJSON("bar/") == "\"bar\\/\"");
assertTrue (toJSON("bar/") == "\"bar/\"");
assertTrue (toJSON("baz") == "\"baz\"");
assertTrue (toJSON("q\"uote\"d") == "\"q\\\"uote\\\"d\"");
assertTrue (toJSON("bs\b") == "\"bs\\b\"");
@@ -1412,7 +1442,7 @@ void StringTest::testJSONString()
ostr.str("");
toJSON("foo\\", ostr);
assertTrue (toJSON("bar/") == "\"bar\\/\"");
assertTrue (toJSON("bar/") == "\"bar/\"");
ostr.str("");
toJSON("baz", ostr);
assertTrue (ostr.str() == "\"baz\"");

View File

@@ -2438,14 +2438,14 @@ void VarTest::testDynamicPair()
catch (InvalidAccessException&) { }
Var va(aPair);
assertTrue ("{ \"0\" : null }" == va.convert<std::string>());
assertTrue ("{ \"0\": null }" == va.convert<std::string>());
assertTrue (aPair.toString() == va.convert<std::string>());
aPair = Pair<int>(4, "123");
assertTrue ("123" == aPair.second());
va = aPair;
assertTrue ("{ \"4\" : \"123\" }" == va.convert<std::string>());
assertTrue ("{ \"4\": \"123\" }" == va.convert<std::string>());
assertTrue (aPair.toString() == va.convert<std::string>());
int i = 1;
@@ -2464,11 +2464,11 @@ void VarTest::testDynamicPair()
assertTrue ("2" == pPair.second());
Var vp(pPair);
assertTrue ("{ \"1\" : \"2\" }" == vp.convert<std::string>());
assertTrue ("{ \"1\": \"2\" }" == vp.convert<std::string>());
assertTrue (pPair.toString() == vp.convert<std::string>());
Var vs(sPair);
assertTrue ("{ \"2\" : 1 }" == vs.convert<std::string>());
assertTrue ("{ \"2\": 1 }" == vs.convert<std::string>());
assertTrue (sPair.toString() == vs.convert<std::string>());
}
@@ -2509,7 +2509,7 @@ void VarTest::testStructToString()
aStruct["Age"] = 1;
Var a1(aStruct);
std::string res = a1.convert<std::string>();
std::string expected = "{ \"Age\" : 1, \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\" }";
std::string expected = "{ \"Age\": 1, \"First Name\": \"Junior\", \"Last Name\": \"POCO\" }";
assertTrue (res == expected);
assertTrue (aStruct.toString() == res);
}
@@ -2523,7 +2523,7 @@ void VarTest::testOrderedStructToString()
aStruct["Age"] = 1;
Var a1(aStruct);
std::string res = a1.convert<std::string>();
std::string expected = "{ \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\", \"Age\" : 1 }";
std::string expected = "{ \"First Name\": \"Junior\", \"Last Name\": \"POCO\", \"Age\": 1 }";
assertTrue(res == expected);
assertTrue(aStruct.toString() == res);
}
@@ -2535,7 +2535,7 @@ void VarTest::testStructToStringEscape()
aStruct["Value"] = "Value with \" and \n";
Var a1(aStruct);
std::string res = a1.convert<std::string>();
std::string expected = "{ \"Value\" : \"Value with \\\" and \\n\" }";
std::string expected = "{ \"Value\": \"Value with \\\" and \\n\" }";
assertTrue (res == expected);
assertTrue (aStruct.toString() == res);
}
@@ -2560,14 +2560,14 @@ void VarTest::testArrayOfStructsToString()
Var a1(s16);
std::string res = a1.convert<std::string>();
std::string expected = "[ "
"{ \"Age\" : 1, \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\" }, "
"{ \"Age\" : 100, \"First Name\" : \"Senior\", \"Last Name\" : \"POCO\" }, "
"{ \"Age\": 1, \"First Name\": \"Junior\", \"Last Name\": \"POCO\" }, "
"{ \"Age\": 100, \"First Name\": \"Senior\", \"Last Name\": \"POCO\" }, "
"[ "
"{ \"Age\" : 1, \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\" }, "
"{ \"Age\" : 100, \"First Name\" : \"Senior\", \"Last Name\" : \"POCO\" }, "
"{ \"Age\": 1, \"First Name\": \"Junior\", \"Last Name\": \"POCO\" }, "
"{ \"Age\": 100, \"First Name\": \"Senior\", \"Last Name\": \"POCO\" }, "
"[ "
"{ \"Age\" : 1, \"First Name\" : \"Junior\", \"Last Name\" : \"POCO\" }, "
"{ \"Age\" : 100, \"First Name\" : \"Senior\", \"Last Name\" : \"POCO\" } "
"{ \"Age\": 1, \"First Name\": \"Junior\", \"Last Name\": \"POCO\" }, "
"{ \"Age\": 100, \"First Name\": \"Senior\", \"Last Name\": \"POCO\" } "
"] ] ]";
assertTrue (res == expected);
@@ -2594,8 +2594,8 @@ void VarTest::testStructWithArraysToString()
aStruct["Address"] = addr;
Var a2(aStruct);
std::string res = a2.convert<std::string>();
std::string expected = "{ \"Address\" : { \"Country\" : \"Carinthia\", \"Number\" : 4, \"Street\" : \"Unknown\" }, "
"\"Age\" : 1, \"First Name\" : \"Junior\", \"Last Name\" : [ \"string\", 23 ] }";
std::string expected = "{ \"Address\": { \"Country\": \"Carinthia\", \"Number\": 4, \"Street\": \"Unknown\" }, "
"\"Age\": 1, \"First Name\": \"Junior\", \"Last Name\": [ \"string\", 23 ] }";
assertTrue (res == expected);
assertTrue (aStruct.toString() == res);
@@ -2615,17 +2615,17 @@ void VarTest::testJSONDeserializeString()
char cc = b2.convert<char>();
assertTrue (cc == 'c');
tst = "{ \"a\" : \"1\", \"b\" : \"2\" \n}";
tst = "{ \"a\": \"1\", \"b\": \"2\" \n}";
a = Var::parse(tst);
assertTrue (a.toString() == "{ \"a\" : \"1\", \"b\" : \"2\" }");
assertTrue (a.toString() == "{ \"a\": \"1\", \"b\": \"2\" }");
tst = "{ \"a\" : \"1\", \"b\" : \"2\"\n}";
tst = "{ \"a\": \"1\", \"b\": \"2\"\n}";
a = Var::parse(tst);
assertTrue (a.toString() == "{ \"a\" : \"1\", \"b\" : \"2\" }");
assertTrue (a.toString() == "{ \"a\": \"1\", \"b\": \"2\" }");
tst = "{ \"message\" : \"escape\\b\\f\\n\\r\\t\", \"path\" : \"\\/dev\\/null\" }";
tst = "{ \"message\": \"escape\\b\\f\\n\\r\\t\", \"path\": \"\\/dev\\/null\", \"zero\": null }";
a = Var::parse(tst);
assertTrue(a.toString() == "{ \"message\" : \"escape\\b\\f\\n\\r\\t\", \"path\" : \"\\/dev\\/null\" }");
assertTrue(a.toString() == "{ \"message\": \"escape\\b\\f\\n\\r\\t\", \"path\": \"/dev/null\", \"zero\": null }");
}
@@ -2859,6 +2859,32 @@ void VarTest::testDate()
}
void VarTest::testUUID()
{
Poco::UUID uuid("f1881be4-c3b7-4a47-9619-5169db5108a7");
Var vuuid(uuid);
assertTrue (vuuid.isUUID());
assert (vuuid.convert<std::string>() == "f1881be4-c3b7-4a47-9619-5169db5108a7");
assert (vuuid.extract<Poco::UUID>() == uuid);
Var vstr(std::string("f1881be4-c3b7-4a47-9619-5169db5108a7"));
assert (vstr.convert<Poco::UUID>() == uuid);
Var vstr2(std::string("notAnUUID"));
try
{
Poco::UUID uuid2 = vstr2.convert<Poco::UUID>();
fail("not a valid UUID, must fail");
}
catch (Poco::SyntaxException&)
{
}
}
void VarTest::testGetIdxNoThrow(Var& a1, std::vector<Var>::size_type n)
{
Var val1 = a1[n];
@@ -2973,8 +2999,15 @@ void VarTest::testEmpty()
void VarTest::testIterator()
{
Var da;
assertTrue (da.isEmpty());
assertTrue (da.begin() == da.end());
try
{
auto it = da.begin();
fail("calling begin() on empty Var must throw");
}
catch (const InvalidAccessException&) { }
da = Poco::Dynamic::Array();
assertTrue(da.begin() == da.end());
da = 1;
assertTrue (!da.isEmpty());
@@ -3097,6 +3130,7 @@ CppUnit::Test* VarTest::suite()
CppUnit_addTest(pSuite, VarTest, testJSONDeserializeComplex);
CppUnit_addTest(pSuite, VarTest, testJSONRoundtripStruct);
CppUnit_addTest(pSuite, VarTest, testDate);
CppUnit_addTest(pSuite, VarTest, testUUID);
CppUnit_addTest(pSuite, VarTest, testEmpty);
CppUnit_addTest(pSuite, VarTest, testIterator);

View File

@@ -71,13 +71,13 @@ public:
void testJSONDeserializePrimitives();
void testJSONDeserializeArray();
void testJSONDeserializeStruct();
void testJSONRoundtripStruct();
void testJSONRoundtripStruct();
void testJSONDeserializeComplex();
void testDate();
void testUUID();
void testEmpty();
void testIterator();
void setUp();
void tearDown();
static CppUnit::Test* suite();
@@ -184,14 +184,29 @@ private:
void testContainerIterator()
{
C cont;
Poco::Dynamic::Var arr(cont);
int counter = 0;
// test empty
assertTrue (arr.size() == 0);
Poco::Dynamic::Var::Iterator it = arr.begin();
Poco::Dynamic::Var::Iterator end = arr.end();
for (; it != end; ++it)
{
*it = ++counter;
}
assertTrue(counter == 0);
// test non-empty
cont.push_back(1);
cont.push_back("2");
cont.push_back(3.5);
Poco::Dynamic::Var arr(cont);
arr = cont;
assertTrue (arr.size() == 3);
Poco::Dynamic::Var::Iterator it = arr.begin();
Poco::Dynamic::Var::Iterator end = arr.end();
int counter = 0;
it = arr.begin();
end = arr.end();
counter = 0;
for (; it != end; ++it)
{
switch (++counter)