DynamicAny improvements (now holds any type out-of-the-box), some refactoring and documentation improvements

This commit is contained in:
Aleksandar Fabijanic 2008-06-30 00:26:54 +00:00
parent e0bb9c162b
commit b1f895eed8
14 changed files with 331 additions and 776 deletions

View File

@ -11,14 +11,6 @@ include $(POCO_BASE)/build/rules/global
SYSFLAGS += -DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK \ SYSFLAGS += -DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK \
-DSQLITE_OMIT_COMPLETE -DSQLITE_OMIT_TCL_VARIABLE -DSQLITE_OMIT_COMPLETE -DSQLITE_OMIT_TCL_VARIABLE
ifeq ($(findstring SunOS,$(POCO_HOST_OSNAME)),SunOS)
POCO_SUN_FORTE = $(findstring SunOS-SunForte, $(POCO_CONFIG))
POCO_SUN_STUDIO = $(findstring SunOS-SunStudio, $(POCO_CONFIG))
ifneq (,$or ($(POCO_SUN_FORTE), $(POCO_SUN_STUDIO)))
CXXFLAGS += -erroff=hidevf
endif
endif
objects = Binder Extractor SessionImpl Connector \ objects = Binder Extractor SessionImpl Connector \
SQLiteException SQLiteStatementImpl Utility \ SQLiteException SQLiteStatementImpl Utility \
sqlite3 sqlite3

View File

@ -252,111 +252,6 @@ public:
return typeid(Data::BLOB); return typeid(Data::BLOB);
} }
void convert(Int8&) const
{
throw Poco::BadCastException();
}
void convert(Int16&) const
{
throw Poco::BadCastException();
}
void convert(Int32&) const
{
throw Poco::BadCastException();
}
void convert(Int64&) const
{
throw Poco::BadCastException();
}
void convert(UInt8&) const
{
throw Poco::BadCastException();
}
void convert(UInt16&) const
{
throw Poco::BadCastException();
}
void convert(UInt32&) const
{
throw Poco::BadCastException();
}
void convert(UInt64&) const
{
throw Poco::BadCastException();
}
void convert(bool&) const
{
throw Poco::BadCastException();
}
void convert(float&) const
{
throw Poco::BadCastException();
}
void convert(double&) const
{
throw Poco::BadCastException();
}
void convert(char&) const
{
throw Poco::BadCastException();
}
void convert(Poco::Timestamp&) const
{
throw Poco::BadCastException();
}
void convert(Poco::DateTime&) const
{
throw Poco::BadCastException();
}
void convert(Poco::LocalDateTime&) const
{
throw Poco::BadCastException();
}
bool isArray() const
{
return false;
}
virtual bool isStruct() const
{
return false;
}
bool isInteger() const
{
return false;
}
bool isSigned() const
{
return false;
}
bool isNumeric() const
{
return false;
}
bool isString() const
{
return false;
}
void convert(std::string& val) const void convert(std::string& val) const
{ {
val.assign(_val.begin(), _val.end()); val.assign(_val.begin(), _val.end());

View File

@ -182,66 +182,6 @@ public:
return typeid(Data::Date); return typeid(Data::Date);
} }
void convert(Int8&) const
{
throw Poco::BadCastException();
}
void convert(Int16&) const
{
throw Poco::BadCastException();
}
void convert(Int32&) const
{
throw Poco::BadCastException();
}
void convert(Int64&) const
{
throw Poco::BadCastException();
}
void convert(UInt8&) const
{
throw Poco::BadCastException();
}
void convert(UInt16&) const
{
throw Poco::BadCastException();
}
void convert(UInt32&) const
{
throw Poco::BadCastException();
}
void convert(UInt64&) const
{
throw Poco::BadCastException();
}
void convert(bool&) const
{
throw Poco::BadCastException();
}
void convert(float&) const
{
throw Poco::BadCastException();
}
void convert(double&) const
{
throw Poco::BadCastException();
}
void convert(char&) const
{
throw Poco::BadCastException();
}
void convert(Poco::Timestamp& val) const void convert(Poco::Timestamp& val) const
{ {
DateTime dt; DateTime dt;
@ -259,36 +199,6 @@ public:
val.assign(_val.year(), _val.month(), _val.day()); val.assign(_val.year(), _val.month(), _val.day());
} }
bool isArray() const
{
return false;
}
virtual bool isStruct() const
{
return false;
}
bool isInteger() const
{
return false;
}
bool isSigned() const
{
return false;
}
bool isNumeric() const
{
return false;
}
bool isString() const
{
return false;
}
void convert(std::string& val) const void convert(std::string& val) const
{ {
DateTime dt(_val.year(), _val.month(), _val.day()); DateTime dt(_val.year(), _val.month(), _val.day());

View File

@ -182,66 +182,6 @@ public:
return typeid(Data::Time); return typeid(Data::Time);
} }
void convert(Int8&) const
{
throw Poco::BadCastException();
}
void convert(Int16&) const
{
throw Poco::BadCastException();
}
void convert(Int32&) const
{
throw Poco::BadCastException();
}
void convert(Int64&) const
{
throw Poco::BadCastException();
}
void convert(UInt8&) const
{
throw Poco::BadCastException();
}
void convert(UInt16&) const
{
throw Poco::BadCastException();
}
void convert(UInt32&) const
{
throw Poco::BadCastException();
}
void convert(UInt64&) const
{
throw Poco::BadCastException();
}
void convert(bool&) const
{
throw Poco::BadCastException();
}
void convert(float&) const
{
throw Poco::BadCastException();
}
void convert(double&) const
{
throw Poco::BadCastException();
}
void convert(char&) const
{
throw Poco::BadCastException();
}
void convert(Poco::Timestamp& val) const void convert(Poco::Timestamp& val) const
{ {
Poco::DateTime dt; Poco::DateTime dt;
@ -263,36 +203,6 @@ public:
val = ldt; val = ldt;
} }
bool isArray() const
{
return false;
}
virtual bool isStruct() const
{
return false;
}
bool isInteger() const
{
return false;
}
bool isSigned() const
{
return false;
}
bool isNumeric() const
{
return false;
}
bool isString() const
{
return false;
}
void convert(std::string& val) const void convert(std::string& val) const
{ {
DateTime dt(0, 1, 1, _val.hour(), _val.minute(), _val.second()); DateTime dt(0, 1, 1, _val.hour(), _val.minute(), _val.second());

View File

@ -64,13 +64,17 @@ Row::Row(NameVecPtr pNames, const RowFormatterPtr& pFormatter):
setFormatter(pFormatter); setFormatter(pFormatter);
// It would be logical for row to be started with empty values NameVec::size_type sz = _pNames->size();
// however, Row sortability at all times is an invariant, hence if (sz)
// we must start with all zeros here. If null values are later {
// retrieved from DB, the DynamicAny::empty() call _values.resize(sz);
// should be used to empty the corresponding Row value // Row sortability at all times is an invariant, hence
_values.resize(_pNames->size(), 0); // we must start with a zero here. If null value is later
addSortField(0); // retrieved from DB, the DynamicAny::empty() call
// should be used to empty the corresponding Row value.
_values[0] = 0;
addSortField(0);
}
} }
@ -122,7 +126,11 @@ void Row::addSortField(std::size_t pos)
} }
ComparisonType ct; ComparisonType ct;
if ((_values[pos].type() == typeid(Poco::Int8)) || if (_values[pos].isEmpty())
{
throw InvalidAccessException("Empty value not sortable.");
}
else if ((_values[pos].type() == typeid(Poco::Int8)) ||
(_values[pos].type() == typeid(Poco::UInt8)) || (_values[pos].type() == typeid(Poco::UInt8)) ||
(_values[pos].type() == typeid(Poco::Int16)) || (_values[pos].type() == typeid(Poco::Int16)) ||
(_values[pos].type() == typeid(Poco::UInt16)) || (_values[pos].type() == typeid(Poco::UInt16)) ||
@ -184,7 +192,7 @@ void Row::replaceSortField(std::size_t oldPos, std::size_t newPos)
if (_values[newPos].isEmpty()) if (_values[newPos].isEmpty())
{ {
throw IllegalStateException("Empty value not sortable."); throw InvalidAccessException("Empty value not sortable.");
} }
else if ((_values[newPos].type() == typeid(Poco::Int8)) || else if ((_values[newPos].type() == typeid(Poco::Int8)) ||
(_values[newPos].type() == typeid(Poco::UInt8)) || (_values[newPos].type() == typeid(Poco::UInt8)) ||

View File

@ -874,6 +874,13 @@ void DataTest::testRow()
fail ("must fail"); fail ("must fail");
}catch (NotFoundException&) {} }catch (NotFoundException&) {}
try
{
row4.addSortField(1);
fail ("must fail - field 1 is empty");
}
catch (InvalidAccessException&) { }
row4.set("field0", 0); row4.set("field0", 0);
row4.set("field1", 1); row4.set("field1", 1);
row4.set("field2", 2); row4.set("field2", 2);

View File

@ -42,6 +42,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/DynamicAnyHolder.h" #include "Poco/DynamicAnyHolder.h"
#include "Poco/Format.h"
#include <typeinfo> #include <typeinfo>
@ -95,7 +96,7 @@ public:
/// Creates an empty DynamicAny. /// Creates an empty DynamicAny.
template <typename T> template <typename T>
DynamicAny(const T &val): DynamicAny(const T& val):
_pHolder(new DynamicAnyHolderImpl<T>(val)) _pHolder(new DynamicAnyHolderImpl<T>(val))
/// Creates the DynamicAny from the given value. /// Creates the DynamicAny from the given value.
{ {
@ -159,7 +160,10 @@ public:
template <typename T> template <typename T>
operator T () const operator T () const
/// Safe conversion operator for implicit type /// Safe conversion operator for implicit type
/// conversions. /// conversions. If the requested type T is same as the
/// type being held, the operation performed is direct
/// extraction, otherwise it is the conversion of the value
/// from type currently held to the one requested.
/// ///
/// Throws a RangeException if the value does not fit /// Throws a RangeException if the value does not fit
/// into the result variable. /// into the result variable.
@ -168,11 +172,16 @@ public:
/// Throws InvalidAccessException if DynamicAny is empty. /// Throws InvalidAccessException if DynamicAny is empty.
{ {
if (!_pHolder) if (!_pHolder)
throw InvalidAccessException("Can not convert empty value."); throw InvalidAccessException("Can not convert empty value.");
T result; if (typeid(T) == _pHolder->type())
_pHolder->convert(result); return extract<T>();
return result; else
{
T result;
_pHolder->convert(result);
return result;
}
} }
template <typename T> template <typename T>
@ -192,7 +201,9 @@ public:
else if (!_pHolder) else if (!_pHolder)
throw InvalidAccessException("Can not extract empty value."); throw InvalidAccessException("Can not extract empty value.");
else else
throw BadCastException(); throw BadCastException(format("Can not convert %s to %s.",
_pHolder->type().name(),
typeid(T).name()));
} }
template <typename T> template <typename T>
@ -373,44 +384,36 @@ public:
template <typename T> template <typename T>
DynamicAny& operator [] (T n) DynamicAny& operator [] (T n)
/// Index operator, only use on DynamicAnys where isArray /// Index operator, only use on DynamicAnys where isArray
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
{ {
DynamicAnyHolderImpl<std::vector<DynamicAny> >* pHolder = return holderImpl<std::vector<DynamicAny>,
dynamic_cast<DynamicAnyHolderImpl<std::vector<DynamicAny> > *>(_pHolder); InvalidAccessException>("Not an array.")->operator[](n);
if (pHolder)
return pHolder->operator[](n);
else
throw BadCastException();
} }
template <typename T> template <typename T>
const DynamicAny& operator [] (T n) const const DynamicAny& operator [] (T n) const
/// const Index operator, only use on DynamicAnys where isArray /// const Index operator, only use on DynamicAnys where isArray
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
{ {
const DynamicAnyHolderImpl<std::vector<DynamicAny> >* pHolder = return const_cast<const DynamicAny&>(holderImpl<std::vector<DynamicAny>,
dynamic_cast<const DynamicAnyHolderImpl<std::vector<DynamicAny> > *>(_pHolder); InvalidAccessException>("Not an array.")->operator[](n));
if (pHolder)
return pHolder->operator[](n);
else
throw BadCastException();
} }
DynamicAny& operator [] (const std::string& name); DynamicAny& operator [] (const std::string& name);
/// Index operator by name, only use on DynamicAnys where isStruct /// Index operator by name, only use on DynamicAnys where isStruct
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
const DynamicAny& operator [] (const std::string& name) const; const DynamicAny& operator [] (const std::string& name) const;
/// Index operator by name, only use on DynamicAnys where isStruct /// Index operator by name, only use on DynamicAnys where isStruct
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
DynamicAny& operator [] (const char* name); DynamicAny& operator [] (const char* name);
/// Index operator by name, only use on DynamicAnys where isStruct /// Index operator by name, only use on DynamicAnys where isStruct
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
const DynamicAny& operator [] (const char* name) const; const DynamicAny& operator [] (const char* name) const;
/// Index operator by name, only use on DynamicAnys where isStruct /// Index operator by name, only use on DynamicAnys where isStruct
/// returns true! In all other cases a BadCastException is thrown! /// returns true! In all other cases InvalidAccessException is thrown.
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.
@ -474,6 +477,17 @@ private:
return convert<T>() / other.convert<T>(); return convert<T>() / other.convert<T>();
} }
template <typename T, typename E>
DynamicAnyHolderImpl<T>* holderImpl(const std::string errorMessage = "") const
{
if (_pHolder && _pHolder->type() == typeid(T))
return static_cast<DynamicAnyHolderImpl<T>*>(_pHolder);
else if (!_pHolder)
throw InvalidAccessException("Can not access empty value.");
else
throw E(errorMessage);
}
DynamicAnyHolder* _pHolder; DynamicAnyHolder* _pHolder;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -247,21 +247,14 @@ DynamicAny DynamicAny::operator -- (int)
DynamicAny& DynamicAny::operator [] (const std::string& name) DynamicAny& DynamicAny::operator [] (const std::string& name)
{ {
DynamicAnyHolderImpl<DynamicStruct>* pHolder = dynamic_cast<DynamicAnyHolderImpl<DynamicStruct> *>(_pHolder); return holderImpl<DynamicStruct, InvalidAccessException>("Not an array.")->operator[](name);
if (pHolder)
return pHolder->operator[](name);
else
throw BadCastException();
} }
const DynamicAny& DynamicAny::operator [] (const std::string& name) const const DynamicAny& DynamicAny::operator [] (const std::string& name) const
{ {
const DynamicAnyHolderImpl<DynamicStruct>* pHolder = dynamic_cast<const DynamicAnyHolderImpl<DynamicStruct>* >(_pHolder); return const_cast<const DynamicAny&>(holderImpl<DynamicStruct,
if (pHolder) InvalidAccessException>("Not an array.")->operator[](name));
return pHolder->operator[](name);
else
throw BadCastException();
} }

View File

@ -47,6 +47,32 @@
using namespace Poco; using namespace Poco;
class Dummy
{
public:
Dummy(): _val(0)
{
}
Dummy(int val): _val(val)
{
}
operator int () const
{
return _val;
}
bool operator == (int i)
{
return i == _val;
}
private:
int _val;
};
DynamicAnyTest::DynamicAnyTest(const std::string& name): CppUnit::TestCase(name) DynamicAnyTest::DynamicAnyTest(const std::string& name): CppUnit::TestCase(name)
{ {
} }
@ -1339,7 +1365,29 @@ void DynamicAnyTest::testULong()
assert (a3 == 64); assert (a3 == 64);
} }
void DynamicAnyTest::testUDT()
{
Dummy d0;
assert (d0 == 0);
Dummy d(1);
DynamicAny da = d;
assert (da.extract<Dummy>() == 1);
Dummy d1 = d;
DynamicAny da1 = d1;
assert (da1.extract<Dummy>() == 1);
try
{
float f = da1;
fail ("must fail");
}
catch (BadCastException&) { }
}
void DynamicAnyTest::testConversionOperator() void DynamicAnyTest::testConversionOperator()
{ {
DynamicAny any("42"); DynamicAny any("42");
@ -2207,7 +2255,7 @@ void DynamicAnyTest::testGetIdxMustThrow(DynamicAny& a1, std::vector<DynamicAny>
fail("bad cast - must throw"); fail("bad cast - must throw");
val1 = 0; // silence the compiler val1 = 0; // silence the compiler
} }
catch (Poco::BadCastException&) catch (Poco::InvalidAccessException&)
{ {
} }
@ -2218,7 +2266,7 @@ void DynamicAnyTest::testGetIdxMustThrow(DynamicAny& a1, std::vector<DynamicAny>
fail("bad const cast - must throw"); fail("bad const cast - must throw");
assert (cval1 == c1); // silence the compiler assert (cval1 == c1); // silence the compiler
} }
catch (Poco::BadCastException&) catch (Poco::InvalidAccessException&)
{ {
} }
} }
@ -2294,9 +2342,10 @@ CppUnit::Test* DynamicAnyTest::suite()
CppUnit_addTest(pSuite, DynamicAnyTest, testChar); CppUnit_addTest(pSuite, DynamicAnyTest, testChar);
CppUnit_addTest(pSuite, DynamicAnyTest, testFloat); CppUnit_addTest(pSuite, DynamicAnyTest, testFloat);
CppUnit_addTest(pSuite, DynamicAnyTest, testDouble); CppUnit_addTest(pSuite, DynamicAnyTest, testDouble);
CppUnit_addTest(pSuite, DynamicAnyTest, testString);
CppUnit_addTest(pSuite, DynamicAnyTest, testLong); CppUnit_addTest(pSuite, DynamicAnyTest, testLong);
CppUnit_addTest(pSuite, DynamicAnyTest, testULong); CppUnit_addTest(pSuite, DynamicAnyTest, testULong);
CppUnit_addTest(pSuite, DynamicAnyTest, testString);
CppUnit_addTest(pSuite, DynamicAnyTest, testUDT);
CppUnit_addTest(pSuite, DynamicAnyTest, testConversionOperator); CppUnit_addTest(pSuite, DynamicAnyTest, testConversionOperator);
CppUnit_addTest(pSuite, DynamicAnyTest, testComparisonOperators); CppUnit_addTest(pSuite, DynamicAnyTest, testComparisonOperators);
CppUnit_addTest(pSuite, DynamicAnyTest, testArithmeticOperators); CppUnit_addTest(pSuite, DynamicAnyTest, testArithmeticOperators);

View File

@ -62,6 +62,7 @@ public:
void testLong(); void testLong();
void testULong(); void testULong();
void testString(); void testString();
void testUDT();
void testConversionOperator(); void testConversionOperator();
void testComparisonOperators(); void testComparisonOperators();
void testArithmeticOperators(); void testArithmeticOperators();
@ -85,6 +86,7 @@ public:
void testDate(); void testDate();
void testEmpty(); void testEmpty();
void setUp(); void setUp();
void tearDown(); void tearDown();
static CppUnit::Test* suite(); static CppUnit::Test* suite();

View File

@ -40,7 +40,7 @@ SHAREDLIBLINKEXT = .so
CFLAGS = -mt -Isrc CFLAGS = -mt -Isrc
CFLAGS32 = CFLAGS32 =
CFLAGS64 = -xarch=v9 CFLAGS64 = -xarch=v9
CXXFLAGS = -mt -library=stlport4 CXXFLAGS = -mt -library=stlport4 -erroff=hidevf
CXXFLAGS32 = CXXFLAGS32 =
CXXFLAGS64 = -xarch=v9 CXXFLAGS64 = -xarch=v9
LINKFLAGS = -mt -library=stlport4 LINKFLAGS = -mt -library=stlport4

View File

@ -40,7 +40,7 @@ SHAREDLIBLINKEXT = .so
CFLAGS = -mt -Isrc CFLAGS = -mt -Isrc
CFLAGS32 = CFLAGS32 =
CFLAGS64 = -m64 CFLAGS64 = -m64
CXXFLAGS = -m32 -mt -library=stlport4 CXXFLAGS = -m32 -mt -library=stlport4 -erroff=hidevf
CXXFLAGS32 = CXXFLAGS32 =
CXXFLAGS64 = -m64 CXXFLAGS64 = -m64
LINKFLAGS = -m32 -mt -library=stlport4 LINKFLAGS = -m32 -mt -library=stlport4

View File

@ -110,6 +110,12 @@ set DEBUG_SHARED=1
set RELEASE_STATIC=1 set RELEASE_STATIC=1
set RELEASE_SHARED=1))))) set RELEASE_SHARED=1)))))
echo Building:
if %DEBUG_SHARED%==1 (echo debug_shared)
if %RELEASE_SHARED%==1 (echo release_shared)
if %DEBUG_STATIC%==1 (echo debug_static)
if %RELEASE_STATIC%==1 (echo release_static)
rem root level components rem root level components
for /f %%G in ('findstr /R /V "./." components') do ( for /f %%G in ('findstr /R /V "./." components') do (
if exist %%G ( if exist %%G (
@ -140,6 +146,7 @@ for /f %%G in ('findstr /R "./." components') do (
) )
) )
if "%SAMPLES%"=="no" goto :EOF if "%SAMPLES%"=="no" goto :EOF
rem root level component samples rem root level component samples