mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-20 22:31:23 +01:00
DynamicAny conversion limits
This commit is contained in:
parent
109a6f47bd
commit
f29f7cda53
@ -49,15 +49,30 @@ namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API DynamicAny
|
||||
/// A DynamicAny allows to store data of different types and to convert between these types transparently.
|
||||
/// It's the reponsibility of the programmer to ensure that conversions are meaningful.
|
||||
/// For example: it is possible to convert between string and character. An empty string gets converted to
|
||||
/// the char '\0', a non-empty string gets truncated to the very first character. Numeric values are truncated,
|
||||
/// no overflow/underflow errors are checked. A string value "false" can be converted to a boolean value false,
|
||||
/// any other string not "false" (not case sensitive) or "0" to true (e.g: "hi" -> true).
|
||||
/// DynamicAny allows to store data of different types and to convert between these types transparently.
|
||||
/// DynamicAny puts forth the best effort to provide intuitive and reasonable conversion semantics and prevent
|
||||
/// unexpected data loss, particularly when performing narrowing or signedness conversions of numeric data types.
|
||||
///
|
||||
/// A DynamicAny can be created from a value of any type for which a
|
||||
/// specialization of DynamicAnyHolderImpl is available.
|
||||
/// Loss of signedness is not allowed for numeric values. This means that if an attempt is made to convert
|
||||
/// the internal value which is a negative signed integer to an unsigned integer type storage, a RangeException is thrown.
|
||||
/// Overflow is not allowed, so if the internal value is a larger number than the target numeric type size can accomodate,
|
||||
/// a RangeException is thrown.
|
||||
///
|
||||
/// Precision loss, such as in conversion from floating-point types to integers or from double to float on platforms
|
||||
/// where they differ in size (provided internal actual value fits in float min/max range), is allowed.
|
||||
///
|
||||
/// String truncation is allowed - it is possible to convert between string and character when string length is
|
||||
/// greater than 1. An empty string gets converted to the char '\0', a non-empty string is truncated to the first character.
|
||||
///
|
||||
/// Bolean conversion are performed as follows:
|
||||
///
|
||||
/// A string value "false" (not case sensitive) or "0" can be converted to a boolean value false, any other string
|
||||
/// not being false by the above criteria evaluates to true (e.g: "hi" -> true).
|
||||
/// Integer 0 values are false, everything else is true.
|
||||
/// Floating point values equal to the minimal FP representation on a given platform are false, everything else is true.
|
||||
///
|
||||
/// A DynamicAny can be created from and converted to a value of any type for which a specialization of
|
||||
/// DynamicAnyHolderImpl is available. For supported types, see DynamicAnyHolder documentation.
|
||||
{
|
||||
public:
|
||||
DynamicAny();
|
||||
|
@ -46,15 +46,46 @@
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <typeinfo>
|
||||
#include <limits>
|
||||
|
||||
///BEGIN ported from boost
|
||||
/// following macros were ported from boost to help the DynamicAnyHolder development
|
||||
/// for complete multi-platform code, see static_assert.hpp in boost libraries
|
||||
|
||||
// Helper macro POCO_JOIN:
|
||||
// The following piece of macro magic joins the two
|
||||
// arguments together, even when one of the arguments is
|
||||
// itself a macro (see 16.3.1 in C++ standard). The key
|
||||
// is that macro expansion of macro arguments does not
|
||||
// occur in POCO_DO_JOIN2 but does in POCO_DO_JOIN.
|
||||
//
|
||||
#define POCO_JOIN(X, Y) POCO_DO_JOIN( X, Y )
|
||||
#define POCO_DO_JOIN(X, Y) POCO_DO_JOIN2(X,Y)
|
||||
#define POCO_DO_JOIN2(X, Y) X##Y
|
||||
|
||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||
template<int x> struct static_assert_test{};
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 3) && ((__GNUC_MINOR__ == 3) || (__GNUC_MINOR__ == 4))
|
||||
# define poco_static_assert( B ) \
|
||||
typedef char POCO_JOIN(poco_static_assert_typedef_, __LINE__) \
|
||||
[ STATIC_ASSERTION_FAILURE< (bool)(B) >::value ]
|
||||
#else
|
||||
# define poco_static_assert(B) \
|
||||
typedef static_assert_test<sizeof(STATIC_ASSERTION_FAILURE<(bool)(B)>)> poco_static_assert_typedef_
|
||||
#endif
|
||||
///END ported from boost
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API DynamicAnyHolder
|
||||
/// Interface for a data holder used by the DynamicAny class. Provides methods to convert between data types.
|
||||
/// Interface for a data holder used by the DynamicAny class.
|
||||
/// Provides methods to convert between data types.
|
||||
/// Only data types for which a convert method exists are supported, which are
|
||||
/// all C++ built-in types, along with std::string.
|
||||
/// all C++ built-in types with addition of std::string.
|
||||
{
|
||||
public:
|
||||
DynamicAnyHolder();
|
||||
@ -88,6 +119,91 @@ public:
|
||||
virtual void convert(double& val) const = 0;
|
||||
virtual void convert(char& val) const = 0;
|
||||
virtual void convert(std::string& val) const = 0;
|
||||
|
||||
protected:
|
||||
template <typename F, typename T>
|
||||
void convertToSmaller(const F& from, T& to) const
|
||||
/// This function is meant to convert signed integral values from
|
||||
/// larger to smaller type. It checks the upper and lower bound and
|
||||
/// if from value is within limits of type T (i.e. check calls do not throw),
|
||||
/// it is converted.
|
||||
{
|
||||
poco_static_assert (std::numeric_limits<F>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<T>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<F>::is_signed);
|
||||
poco_static_assert (std::numeric_limits<T>::is_signed);
|
||||
|
||||
checkUpperLimit(from, to);
|
||||
checkLowerLimit(from, to);
|
||||
to = static_cast<T>(from);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void convertToSmallerUnsigned(const F& from, T& to) const
|
||||
/// This function is meant for converting unsigned integral data types,
|
||||
/// from larger to smaller type. Since lower limit is always 0 for unigned types,
|
||||
/// only the upper limit is checked, thus saving some cycles compared to the signed
|
||||
/// version of the function. If the value to be converted is smaller than
|
||||
/// the maximum value for the target type, the conversion is performed.
|
||||
{
|
||||
poco_static_assert (std::numeric_limits<F>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<T>::is_specialized);
|
||||
poco_static_assert (!std::numeric_limits<F>::is_signed);
|
||||
poco_static_assert (!std::numeric_limits<T>::is_signed);
|
||||
|
||||
checkUpperLimit(from, to);
|
||||
to = static_cast<T>(from);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void convertSignedToUnsigned(const F& from, T& to) const
|
||||
/// This function is meant for converting signed integral data types to
|
||||
/// unsigned data types. Negative values can not be converted and if one is
|
||||
/// encountered, RangeException is thrown.
|
||||
/// If uper limit is within the target data type limits, the converiosn is performed.
|
||||
{
|
||||
poco_static_assert (std::numeric_limits<F>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<T>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<F>::is_signed);
|
||||
poco_static_assert (!std::numeric_limits<T>::is_signed);
|
||||
|
||||
if (from < 0)
|
||||
throw RangeException("Value too small.");
|
||||
checkUpperLimit(from, to);
|
||||
to = static_cast<T>(from);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void convertUnsignedToSigned(const F& from, T& to) const
|
||||
/// This function is meant for converting unsigned integral data types to
|
||||
/// unsigned data types. Negative values can not be converted and if one is
|
||||
/// encountered, RangeException is thrown.
|
||||
/// If uper limit is within the target data type limits, the converiosn is performed.
|
||||
{
|
||||
poco_static_assert (std::numeric_limits<F>::is_specialized);
|
||||
poco_static_assert (std::numeric_limits<T>::is_specialized);
|
||||
poco_static_assert (!std::numeric_limits<F>::is_signed);
|
||||
poco_static_assert (std::numeric_limits<T>::is_signed);
|
||||
|
||||
checkUpperLimit(from, to);
|
||||
to = static_cast<T>(from);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F, typename T>
|
||||
void checkUpperLimit(const F& from, T& to) const
|
||||
{
|
||||
if (from > std::numeric_limits<T>::max())
|
||||
throw RangeException("Value too large.");
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
void checkLowerLimit(const F& from, T& to) const
|
||||
{
|
||||
if (from < std::numeric_limits<T>::min())
|
||||
throw RangeException("Value too small.");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -119,6 +235,11 @@ class DynamicAnyHolderImpl: public DynamicAnyHolder
|
||||
///
|
||||
/// DynamicAny can be used for any type for which a specialization for
|
||||
/// DynamicAnyHolderImpl is available.
|
||||
///
|
||||
/// DynamicAnyHolderImpl throws following exceptions:
|
||||
/// NotImplementedException (if the specialization for a type does not exist)
|
||||
/// RangeException (if an attempt is made to assign a numeric value outside of the target min/max limits
|
||||
/// SyntaxException (if an attempt is made to convert a string containing non-numeric characters to number)
|
||||
{
|
||||
DynamicAnyHolderImpl()
|
||||
{
|
||||
@ -245,22 +366,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -318,7 +439,7 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
@ -338,22 +459,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -373,7 +494,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -410,12 +531,12 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
@ -430,22 +551,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -465,7 +586,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -502,17 +623,17 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
@ -522,22 +643,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -557,7 +678,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -594,12 +715,12 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
@ -649,7 +770,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -686,17 +807,17 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
@ -706,7 +827,7 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
@ -741,7 +862,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -778,32 +899,32 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
{
|
||||
val = static_cast<Int64>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
@ -833,7 +954,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -870,37 +991,37 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
{
|
||||
val = static_cast<Int64>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
@ -925,7 +1046,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -1054,47 +1175,48 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
{
|
||||
val = static_cast<Int64>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
{
|
||||
val = !(_val < 0.0001f && _val > -0.0001f);
|
||||
val = !(_val <= std::numeric_limits<float>::min() &&
|
||||
_val >= -1 * std::numeric_limits<float>::min());
|
||||
}
|
||||
|
||||
void convert(float& val) const
|
||||
@ -1109,7 +1231,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -1146,51 +1268,58 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
{
|
||||
val = static_cast<Int64>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
{
|
||||
val = !(_val < 0.0001 && _val > -0.0001);
|
||||
val = !(_val <= std::numeric_limits<double>::min() &&
|
||||
_val >= -1 * std::numeric_limits<double>::min());
|
||||
}
|
||||
|
||||
void convert(float& val) const
|
||||
{
|
||||
double fMin = -1 * std::numeric_limits<float>::max();
|
||||
double fMax = std::numeric_limits<float>::max();
|
||||
|
||||
if (_val < fMin) throw RangeException("Value too small.");
|
||||
if (_val > fMax) throw RangeException("Value too large.");
|
||||
|
||||
val = static_cast<float>(_val);
|
||||
}
|
||||
|
||||
@ -1201,7 +1330,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -1258,22 +1387,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -1334,12 +1463,14 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(NumberParser::parse(_val));
|
||||
int v = NumberParser::parse(_val);
|
||||
convertToSmaller(v, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(NumberParser::parse(_val));
|
||||
int v = NumberParser::parse(_val);
|
||||
convertToSmaller(v, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
@ -1354,12 +1485,14 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(NumberParser::parseUnsigned(_val));
|
||||
unsigned int v = NumberParser::parseUnsigned(_val);
|
||||
convertToSmallerUnsigned(v, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(NumberParser::parseUnsigned(_val));
|
||||
unsigned int v = NumberParser::parseUnsigned(_val);
|
||||
convertToSmallerUnsigned(v, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
@ -1385,7 +1518,8 @@ public:
|
||||
|
||||
void convert(float& val) const
|
||||
{
|
||||
val = static_cast<float>(NumberParser::parseFloat(_val));
|
||||
double v = NumberParser::parseFloat(_val);
|
||||
convertToSmaller(v, val);
|
||||
}
|
||||
|
||||
void convert(double& val) const
|
||||
@ -1438,12 +1572,12 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
@ -1458,22 +1592,22 @@ public:
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
{
|
||||
val = static_cast<UInt64>(_val);
|
||||
convertSignedToUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(bool& val) const
|
||||
@ -1493,7 +1627,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertToSmaller(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
@ -1530,37 +1664,37 @@ public:
|
||||
|
||||
void convert(Int8& val) const
|
||||
{
|
||||
val = static_cast<Int8>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int16& val) const
|
||||
{
|
||||
val = static_cast<Int16>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int32& val) const
|
||||
{
|
||||
val = static_cast<Int32>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(Int64& val) const
|
||||
{
|
||||
val = static_cast<Int64>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt8& val) const
|
||||
{
|
||||
val = static_cast<UInt8>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt16& val) const
|
||||
{
|
||||
val = static_cast<UInt16>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt32& val) const
|
||||
{
|
||||
val = static_cast<UInt32>(_val);
|
||||
convertToSmallerUnsigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(UInt64& val) const
|
||||
@ -1585,7 +1719,7 @@ public:
|
||||
|
||||
void convert(char& val) const
|
||||
{
|
||||
val = static_cast<char>(_val);
|
||||
convertUnsignedToSigned(_val, val);
|
||||
}
|
||||
|
||||
void convert(std::string& val) const
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "Poco/Bugcheck.h"
|
||||
|
||||
|
||||
|
||||
using namespace Poco;
|
||||
|
||||
|
||||
@ -940,11 +939,91 @@ void DynamicAnyTest::testConversionOperator()
|
||||
assert (i == 42);
|
||||
|
||||
any = 123;
|
||||
std::string s(any);
|
||||
std::string s = any;//'s(any)' bombs on gcc 3.4.4
|
||||
assert (s == "123");
|
||||
}
|
||||
|
||||
|
||||
void DynamicAnyTest::testLimitsInt()
|
||||
{
|
||||
testLimitsSigned<Int16, Int8>();
|
||||
testLimitsSigned<Int32, Int8>();
|
||||
testLimitsSigned<Int64, Int8>();
|
||||
testLimitsFloatToInt<float, Int8>();
|
||||
testLimitsFloatToInt<double, Int8>();
|
||||
|
||||
testLimitsSigned<Int16, char>();
|
||||
testLimitsSigned<Int32, char>();
|
||||
testLimitsSigned<Int64, char>();
|
||||
testLimitsFloatToInt<float, char>();
|
||||
testLimitsFloatToInt<double, char>();
|
||||
|
||||
testLimitsSigned<Int32, Int16>();
|
||||
testLimitsSigned<Int64, Int16>();
|
||||
testLimitsFloatToInt<float, Int16>();
|
||||
testLimitsFloatToInt<double, Int16>();
|
||||
|
||||
testLimitsSigned<Int64, Int32>();
|
||||
testLimitsFloatToInt<float, Int32>();
|
||||
testLimitsFloatToInt<double, Int32>();
|
||||
|
||||
testLimitsSignedUnsigned<Int8, UInt8>();
|
||||
testLimitsSignedUnsigned<Int16, UInt8>();
|
||||
testLimitsSignedUnsigned<Int32, UInt8>();
|
||||
testLimitsSignedUnsigned<Int64, UInt8>();
|
||||
testLimitsFloatToInt<float, UInt8>();
|
||||
testLimitsFloatToInt<double, UInt8>();
|
||||
|
||||
testLimitsSignedUnsigned<Int8, UInt16>();
|
||||
testLimitsSignedUnsigned<Int16, UInt16>();
|
||||
testLimitsSignedUnsigned<Int32, UInt16>();
|
||||
testLimitsSignedUnsigned<Int64, UInt16>();
|
||||
testLimitsFloatToInt<float, UInt16>();
|
||||
testLimitsFloatToInt<double, UInt16>();
|
||||
|
||||
testLimitsSignedUnsigned<Int8, UInt32>();
|
||||
testLimitsSignedUnsigned<Int16, UInt32>();
|
||||
testLimitsSignedUnsigned<Int32, UInt32>();
|
||||
testLimitsSignedUnsigned<Int64, UInt32>();
|
||||
testLimitsFloatToInt<float, UInt32>();
|
||||
testLimitsFloatToInt<double, UInt32>();
|
||||
|
||||
testLimitsSignedUnsigned<Int8, UInt64>();
|
||||
testLimitsSignedUnsigned<Int16, UInt64>();
|
||||
testLimitsSignedUnsigned<Int32, UInt64>();
|
||||
testLimitsSignedUnsigned<Int64, UInt64>();
|
||||
testLimitsFloatToInt<float, UInt64>();
|
||||
testLimitsFloatToInt<double, UInt64>();
|
||||
|
||||
|
||||
testLimitsUnsigned<UInt16, UInt8>();
|
||||
testLimitsUnsigned<UInt32, UInt8>();
|
||||
testLimitsUnsigned<UInt64, UInt8>();
|
||||
|
||||
testLimitsUnsigned<UInt32, UInt16>();
|
||||
testLimitsUnsigned<UInt64, UInt16>();
|
||||
|
||||
testLimitsUnsigned<UInt64, UInt32>();
|
||||
}
|
||||
|
||||
|
||||
void DynamicAnyTest::testLimitsFloat()
|
||||
{
|
||||
if (std::numeric_limits<double>::max() != std::numeric_limits<float>::max())
|
||||
{
|
||||
double iMin = -1 * std::numeric_limits<float>::max();
|
||||
DynamicAny da = iMin * 10;
|
||||
try { float f; f = da; fail("must fail"); }
|
||||
catch (RangeException&) {}
|
||||
|
||||
double iMax = std::numeric_limits<float>::max();
|
||||
da = iMax * 10;
|
||||
try { float f; f = da; fail("must fail"); }
|
||||
catch (RangeException&) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DynamicAnyTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -975,6 +1054,8 @@ CppUnit::Test* DynamicAnyTest::suite()
|
||||
CppUnit_addTest(pSuite, DynamicAnyTest, testLong);
|
||||
CppUnit_addTest(pSuite, DynamicAnyTest, testULong);
|
||||
CppUnit_addTest(pSuite, DynamicAnyTest, testConversionOperator);
|
||||
CppUnit_addTest(pSuite, DynamicAnyTest, testLimitsInt);
|
||||
CppUnit_addTest(pSuite, DynamicAnyTest, testLimitsFloat);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
@ -61,10 +63,67 @@ public:
|
||||
void testULong();
|
||||
void testString();
|
||||
void testConversionOperator();
|
||||
|
||||
void testLimitsInt();
|
||||
void testLimitsFloat();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
template<typename TL, typename TS>
|
||||
void testLimitsSigned()
|
||||
{
|
||||
TL iMin = std::numeric_limits<TS>::min();
|
||||
Poco::DynamicAny da = iMin - 1;
|
||||
try { TS i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
|
||||
TL iMax = std::numeric_limits<TS>::max();
|
||||
da = iMax + 1;
|
||||
try { TS i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
|
||||
template<typename TL, typename TS>
|
||||
void testLimitsFloatToInt()
|
||||
{
|
||||
Poco::DynamicAny da;
|
||||
|
||||
if (std::numeric_limits<TS>::is_signed)
|
||||
{
|
||||
TL iMin = static_cast<TL>(std::numeric_limits<TS>::min());
|
||||
da = iMin * 10;
|
||||
try { TS i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
|
||||
TL iMax = static_cast<TL>(std::numeric_limits<TS>::max());
|
||||
da = iMax * 10;
|
||||
try { TS i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
|
||||
template<typename TS, typename TU>
|
||||
void testLimitsSignedUnsigned()
|
||||
{
|
||||
assert (std::numeric_limits<TS>::is_signed);
|
||||
assert (!std::numeric_limits<TU>::is_signed);
|
||||
|
||||
TS iMin = std::numeric_limits<TS>::min();
|
||||
Poco::DynamicAny da = iMin;
|
||||
try { TU i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
|
||||
template<typename TL, typename TS>
|
||||
void testLimitsUnsigned()
|
||||
{
|
||||
TL iMax = std::numeric_limits<TS>::max();
|
||||
Poco::DynamicAny da = iMax + 1;
|
||||
try { TS i; i = da; fail("must fail"); }
|
||||
catch (Poco::RangeException&) {}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user