DynamicAny non-initialized state capability

made DynamicAnyHolder::create() and is...() pure virtual functions virtual
(simplifies DynamicAnyHolderImpl implementation)
made DynamicAnyHolder default constructor protected
made DynamicAnyHolderImpl default constructor private
added DynamicAnyTest::testEmpty()
This commit is contained in:
Aleksandar Fabijanic 2008-06-23 02:15:22 +00:00
parent c896a9b474
commit b044856f46
8 changed files with 246 additions and 134 deletions

View File

@ -373,6 +373,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Data::BLOB _val; Data::BLOB _val;
}; };

View File

@ -306,6 +306,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Data::Date _val; Data::Date _val;
}; };

View File

@ -310,6 +310,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Data::Time _val; Data::Time _val;
}; };

View File

@ -53,6 +53,9 @@ class Foundation_API DynamicAny
/// DynamicAny puts forth the best effort to provide intuitive and reasonable conversion semantics and prevent /// 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. /// unexpected data loss, particularly when performing narrowing or signedness conversions of numeric data types.
/// ///
/// An attempt to convert or extract from a non-initialized (“empty”) DynamicAny variable shall result
/// in an exception being thrown.
///
/// Loss of signedness is not allowed for numeric values. This means that if an attempt is made to convert /// 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. /// 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, /// Overflow is not allowed, so if the internal value is a larger number than the target numeric type size can accomodate,
@ -89,7 +92,7 @@ class Foundation_API DynamicAny
{ {
public: public:
DynamicAny(); DynamicAny();
/// Creates a DynamicAny holding an int with value 0. /// Creates an empty DynamicAny.
template <typename T> template <typename T>
DynamicAny(const T &val): DynamicAny(const T &val):
@ -123,7 +126,11 @@ public:
/// into the result variable. /// into the result variable.
/// Throws a NotImplementedException if conversion is /// Throws a NotImplementedException if conversion is
/// not available for the given type. /// not available for the given type.
/// Throws InvalidAccessException if DynamicAny is empty.
{ {
if (!_pHolder)
throw InvalidAccessException("Can not convert empty value.");
_pHolder->convert(val); _pHolder->convert(val);
} }
@ -139,7 +146,11 @@ public:
/// into the result variable. /// into the result variable.
/// Throws a NotImplementedException if conversion is /// Throws a NotImplementedException if conversion is
/// not available for the given type. /// not available for the given type.
/// Throws InvalidAccessException if DynamicAny is empty.
{ {
if (!_pHolder)
throw InvalidAccessException("Can not convert empty value.");
T result; T result;
_pHolder->convert(result); _pHolder->convert(result);
return result; return result;
@ -154,7 +165,11 @@ public:
/// into the result variable. /// into the result variable.
/// Throws a NotImplementedException if conversion is /// Throws a NotImplementedException if conversion is
/// not available for the given type. /// not available for the given type.
/// Throws InvalidAccessException if DynamicAny is empty.
{ {
if (!_pHolder)
throw InvalidAccessException("Can not convert empty value.");
T result; T result;
_pHolder->convert(result); _pHolder->convert(result);
return result; return result;
@ -167,12 +182,15 @@ public:
/// Must be instantiated with the exact type of /// Must be instantiated with the exact type of
/// the stored value, otherwise a BadCastException /// the stored value, otherwise a BadCastException
/// is thrown. /// is thrown.
/// Throws InvalidAccessException if DynamicAny is empty.
{ {
if (_pHolder && _pHolder->type() == typeid(T)) if (_pHolder && _pHolder->type() == typeid(T))
{ {
DynamicAnyHolderImpl<T>* pHolder = static_cast<DynamicAnyHolderImpl<T>*>(_pHolder); DynamicAnyHolderImpl<T>* pHolderImpl = static_cast<DynamicAnyHolderImpl<T>*>(_pHolder);
return pHolder->value(); return pHolderImpl->value();
} }
else if (!_pHolder)
throw InvalidAccessException("Can not extract empty value.");
else else
throw BadCastException(); throw BadCastException();
} }
@ -397,6 +415,12 @@ public:
const std::type_info& type() const; const std::type_info& type() const;
/// Returns the type information of the stored content. /// Returns the type information of the stored content.
void empty();
/// Empties DynamicAny.
bool isEmpty() const;
/// Returns true if empty.
bool isInteger() const; bool isInteger() const;
/// Returns true if stored value is integer. /// Returns true if stored value is integer.
@ -523,6 +547,19 @@ inline bool DynamicAny::operator != (const char* other) const
} }
inline void DynamicAny::empty()
{
delete _pHolder;
_pHolder = 0;
}
inline bool DynamicAny::isEmpty() const
{
return 0 == _pHolder;
}
inline bool DynamicAny::isArray() const inline bool DynamicAny::isArray() const
{ {
return _pHolder->isArray(); return _pHolder->isArray();

View File

@ -76,9 +76,6 @@ class Foundation_API DynamicAnyHolder
/// std::vector<DynamicAny> and DynamicStruct. /// std::vector<DynamicAny> and DynamicStruct.
{ {
public: public:
DynamicAnyHolder();
/// Creates the DynamicAnyHolder.
virtual ~DynamicAnyHolder(); virtual ~DynamicAnyHolder();
/// Destroys the DynamicAnyHolder. /// Destroys the DynamicAnyHolder.
@ -88,36 +85,38 @@ public:
virtual const std::type_info& type() const = 0; virtual const std::type_info& type() const = 0;
/// Returns the type information of the stored content. /// Returns the type information of the stored content.
virtual void convert(Int8& val) const = 0; virtual void convert(Int8& val) const;
virtual void convert(Int16& val) const = 0; virtual void convert(Int16& val) const;
virtual void convert(Int32& val) const = 0; virtual void convert(Int32& val) const;
virtual void convert(Int64& val) const = 0; virtual void convert(Int64& val) const;
virtual void convert(UInt8& val) const = 0; virtual void convert(UInt8& val) const;
virtual void convert(UInt16& val) const = 0; virtual void convert(UInt16& val) const;
virtual void convert(UInt32& val) const = 0; virtual void convert(UInt32& val) const;
virtual void convert(UInt64& val) const = 0; virtual void convert(UInt64& val) const;
virtual void convert(DateTime& val) const = 0; virtual void convert(DateTime& val) const;
virtual void convert(LocalDateTime& val) const = 0; virtual void convert(LocalDateTime& val) const;
virtual void convert(Timestamp& val) const = 0; virtual void convert(Timestamp& val) const;
virtual bool isArray() const = 0;
virtual bool isStruct() const = 0;
virtual bool isInteger() const = 0;
virtual bool isSigned() const = 0;
virtual bool isNumeric() const = 0;
virtual bool isString() const = 0;
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void convert(long& val) const; void convert(long& val) const;
void convert(unsigned long& val) const; void convert(unsigned long& val) const;
#endif #endif
virtual void convert(bool& val) const;
virtual void convert(float& val) const;
virtual void convert(double& val) const;
virtual void convert(char& val) const;
virtual void convert(std::string& val) const;
virtual void convert(bool& val) const = 0; virtual bool isArray() const;
virtual void convert(float& val) const = 0; virtual bool isStruct() const;
virtual void convert(double& val) const = 0; virtual bool isInteger() const;
virtual void convert(char& val) const = 0; virtual bool isSigned() const;
virtual void convert(std::string& val) const = 0; virtual bool isNumeric() const;
virtual bool isString() const;
protected: protected:
DynamicAnyHolder();
/// Creates the DynamicAnyHolder.
template <typename F, typename T> template <typename F, typename T>
void convertToSmaller(const F& from, T& to) const void convertToSmaller(const F& from, T& to) const
/// This function is meant to convert signed numeric values from /// This function is meant to convert signed numeric values from
@ -244,6 +243,73 @@ private:
// //
// inlines // inlines
// //
inline void DynamicAnyHolder::convert(Int8& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for Int8");
}
inline void DynamicAnyHolder::convert(Int16& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for Int16");
}
inline void DynamicAnyHolder::convert(Int32& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for Int32");
}
inline void DynamicAnyHolder::convert(Int64& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for Int64");
}
inline void DynamicAnyHolder::convert(UInt8& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for UInt8");
}
inline void DynamicAnyHolder::convert(UInt16& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for UInt16");
}
inline void DynamicAnyHolder::convert(UInt32& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for UInt32");
}
inline void DynamicAnyHolder::convert(UInt64& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for UInt64");
}
inline void DynamicAnyHolder::convert(DateTime& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for DateTime");
}
inline void DynamicAnyHolder::convert(LocalDateTime& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for LocalDateTime");
}
inline void DynamicAnyHolder::convert(Timestamp& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for Timestamp");
}
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
inline void DynamicAnyHolder::convert(long& val) const inline void DynamicAnyHolder::convert(long& val) const
{ {
@ -261,6 +327,61 @@ inline void DynamicAnyHolder::convert(unsigned long& val) const
} }
#endif #endif
inline void DynamicAnyHolder::convert(bool& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for bool");
}
inline void DynamicAnyHolder::convert(float& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for float");
}
inline void DynamicAnyHolder::convert(double& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for double");
}
inline void DynamicAnyHolder::convert(char& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for char");
}
inline void DynamicAnyHolder::convert(std::string& val) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for std::string");
}
inline bool DynamicAnyHolder::isArray() const
{
return false;
}
inline bool DynamicAnyHolder::isStruct() const
{
return false;
}
inline bool DynamicAnyHolder::isInteger() const
{
return false;
}
inline bool DynamicAnyHolder::isSigned() const
{
return false;
}
inline bool DynamicAnyHolder::isNumeric() const
{
return false;
}
inline bool DynamicAnyHolder::isString() const
{
return false;
}
template <typename T> template <typename T>
class DynamicAnyHolderImpl: public DynamicAnyHolder class DynamicAnyHolderImpl: public DynamicAnyHolder
@ -280,10 +401,6 @@ class DynamicAnyHolderImpl: public DynamicAnyHolder
/// returning a const reference to the actual stored value. /// returning a const reference to the actual stored value.
{ {
public: public:
DynamicAnyHolderImpl()
{
}
~DynamicAnyHolderImpl() ~DynamicAnyHolderImpl()
{ {
} }
@ -313,100 +430,8 @@ public:
return type() == typeid(std::string); return type() == typeid(std::string);
} }
void convert(Int8&) const private:
{ DynamicAnyHolderImpl();
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(Int16&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(Int32&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(Int64&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(UInt8&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(UInt16&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(UInt32&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(UInt64&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(bool&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(float&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(double&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(char&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(std::string&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(DateTime&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(LocalDateTime&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
void convert(Timestamp&) const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
DynamicAnyHolder* clone() const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
bool isArray() const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
bool isStruct() const
{
throw NotImplementedException("No DynamicAnyHolder specialization for type", typeid(T).name());
}
}; };
@ -548,6 +573,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Int8 _val; Int8 _val;
}; };
@ -692,6 +718,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Int16 _val; Int16 _val;
}; };
@ -836,6 +863,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Int32 _val; Int32 _val;
}; };
@ -980,6 +1008,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Int64 _val; Int64 _val;
}; };
@ -1124,6 +1153,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
UInt8 _val; UInt8 _val;
}; };
@ -1268,6 +1298,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
UInt16 _val; UInt16 _val;
}; };
@ -1412,6 +1443,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
UInt32 _val; UInt32 _val;
}; };
@ -1562,6 +1594,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
UInt64 _val; UInt64 _val;
}; };
@ -1704,6 +1737,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
bool _val; bool _val;
}; };
@ -1849,6 +1883,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
float _val; float _val;
}; };
@ -2000,6 +2035,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
double _val; double _val;
}; };
@ -2142,6 +2178,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
char _val; char _val;
}; };
@ -2317,6 +2354,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
std::string _val; std::string _val;
}; };
@ -2464,6 +2502,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
long _val; long _val;
}; };
@ -2608,6 +2647,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
unsigned long _val; unsigned long _val;
}; };
@ -2694,8 +2734,8 @@ public:
void convert(std::string& val) const void convert(std::string& val) const
{ {
// Serialize in JSON format: note: although this a vector<T>, the code only // Serialize in JSON format: note: although this is a vector<T>, the code only
// supports vector<DynamicAny>. We can't make this a total specialization, // supports vector<DynamicAny>. Total specialization is not possible
// because of the cyclic dependency between DynamicAny and DynamicAnyHolder // because of the cyclic dependency between DynamicAny and DynamicAnyHolder
// JSON format definition: [ n times: elem ',' ], no ',' for last elem // JSON format definition: [ n times: elem ',' ], no ',' for last elem
@ -2718,17 +2758,17 @@ public:
void convert(DateTime&) const void convert(DateTime&) const
{ {
throw BadCastException("vector -> DateTime"); throw BadCastException("Cannot cast collection type to non-collection type");
} }
void convert(LocalDateTime&) const void convert(LocalDateTime&) const
{ {
throw BadCastException("vector -> LocalDateTime"); throw BadCastException("Cannot cast collection type to non-collection type");
} }
void convert(Timestamp&) const void convert(Timestamp&) const
{ {
throw BadCastException("vector -> Timestamp"); throw BadCastException("Cannot cast collection type to non-collection type");
} }
DynamicAnyHolder* clone() const DynamicAnyHolder* clone() const
@ -2782,6 +2822,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
std::vector<T> _val; std::vector<T> _val;
}; };
@ -2924,6 +2965,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
DateTime _val; DateTime _val;
}; };
@ -3066,6 +3108,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
LocalDateTime _val; LocalDateTime _val;
}; };
@ -3208,6 +3251,7 @@ public:
} }
private: private:
DynamicAnyHolderImpl();
Timestamp _val; Timestamp _val;
}; };

View File

@ -43,8 +43,7 @@
namespace Poco { namespace Poco {
DynamicAny::DynamicAny(): DynamicAny::DynamicAny(): _pHolder(0)
_pHolder(new DynamicAnyHolderImpl<int>(0))
{ {
} }

View File

@ -2224,6 +2224,33 @@ void DynamicAnyTest::testGetIdxMustThrow(DynamicAny& a1, std::vector<DynamicAny>
} }
void DynamicAnyTest::testEmpty()
{
DynamicAny da;
assert (da.isEmpty());
da = "123";
int i = da.convert<int>();
assert (123 == i);
std::string s = da.extract<std::string>();
assert ("123" == s);
assert (!da.isEmpty());
da.empty();
assert (da.isEmpty());
try
{
int i = da;
fail ("must fail");
} catch (InvalidAccessException&) { }
try
{
int i = da.extract<int>();
fail ("must fail");
} catch (InvalidAccessException&) { }
}
void DynamicAnyTest::setUp() void DynamicAnyTest::setUp()
{ {
} }
@ -2274,6 +2301,7 @@ CppUnit::Test* DynamicAnyTest::suite()
CppUnit_addTest(pSuite, DynamicAnyTest, testJSONDeserializeStruct); CppUnit_addTest(pSuite, DynamicAnyTest, testJSONDeserializeStruct);
CppUnit_addTest(pSuite, DynamicAnyTest, testJSONDeserializeComplex); CppUnit_addTest(pSuite, DynamicAnyTest, testJSONDeserializeComplex);
CppUnit_addTest(pSuite, DynamicAnyTest, testDate); CppUnit_addTest(pSuite, DynamicAnyTest, testDate);
CppUnit_addTest(pSuite, DynamicAnyTest, testEmpty);
return pSuite; return pSuite;
} }

View File

@ -83,6 +83,7 @@ public:
void testJSONDeserializeStruct(); void testJSONDeserializeStruct();
void testJSONDeserializeComplex(); void testJSONDeserializeComplex();
void testDate(); void testDate();
void testEmpty();
void setUp(); void setUp();
void tearDown(); void tearDown();