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 \
-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 \
SQLiteException SQLiteStatementImpl Utility \
sqlite3

View File

@ -252,111 +252,6 @@ public:
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
{
val.assign(_val.begin(), _val.end());

View File

@ -182,66 +182,6 @@ public:
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
{
DateTime dt;
@ -259,36 +199,6 @@ public:
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
{
DateTime dt(_val.year(), _val.month(), _val.day());

View File

@ -182,66 +182,6 @@ public:
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
{
Poco::DateTime dt;
@ -263,36 +203,6 @@ public:
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
{
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);
// It would be logical for row to be started with empty values
// however, Row sortability at all times is an invariant, hence
// we must start with all zeros here. If null values are later
// retrieved from DB, the DynamicAny::empty() call
// should be used to empty the corresponding Row value
_values.resize(_pNames->size(), 0);
addSortField(0);
NameVec::size_type sz = _pNames->size();
if (sz)
{
_values.resize(sz);
// Row sortability at all times is an invariant, hence
// we must start with a zero here. If null value is later
// 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;
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::Int16)) ||
(_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())
{
throw IllegalStateException("Empty value not sortable.");
throw InvalidAccessException("Empty value not sortable.");
}
else if ((_values[newPos].type() == typeid(Poco::Int8)) ||
(_values[newPos].type() == typeid(Poco::UInt8)) ||

View File

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

View File

@ -42,6 +42,7 @@
#include "Poco/Foundation.h"
#include "Poco/DynamicAnyHolder.h"
#include "Poco/Format.h"
#include <typeinfo>
@ -95,7 +96,7 @@ public:
/// Creates an empty DynamicAny.
template <typename T>
DynamicAny(const T &val):
DynamicAny(const T& val):
_pHolder(new DynamicAnyHolderImpl<T>(val))
/// Creates the DynamicAny from the given value.
{
@ -159,7 +160,10 @@ public:
template <typename T>
operator T () const
/// 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
/// into the result variable.
@ -168,11 +172,16 @@ public:
/// Throws InvalidAccessException if DynamicAny is empty.
{
if (!_pHolder)
throw InvalidAccessException("Can not convert empty value.");
throw InvalidAccessException("Can not convert empty value.");
T result;
_pHolder->convert(result);
return result;
if (typeid(T) == _pHolder->type())
return extract<T>();
else
{
T result;
_pHolder->convert(result);
return result;
}
}
template <typename T>
@ -192,7 +201,9 @@ public:
else if (!_pHolder)
throw InvalidAccessException("Can not extract empty value.");
else
throw BadCastException();
throw BadCastException(format("Can not convert %s to %s.",
_pHolder->type().name(),
typeid(T).name()));
}
template <typename T>
@ -373,44 +384,36 @@ public:
template <typename T>
DynamicAny& operator [] (T n)
/// 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 =
dynamic_cast<DynamicAnyHolderImpl<std::vector<DynamicAny> > *>(_pHolder);
if (pHolder)
return pHolder->operator[](n);
else
throw BadCastException();
return holderImpl<std::vector<DynamicAny>,
InvalidAccessException>("Not an array.")->operator[](n);
}
template <typename T>
const DynamicAny& operator [] (T n) const
/// 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 =
dynamic_cast<const DynamicAnyHolderImpl<std::vector<DynamicAny> > *>(_pHolder);
if (pHolder)
return pHolder->operator[](n);
else
throw BadCastException();
return const_cast<const DynamicAny&>(holderImpl<std::vector<DynamicAny>,
InvalidAccessException>("Not an array.")->operator[](n));
}
DynamicAny& operator [] (const std::string& name);
/// 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;
/// 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);
/// 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;
/// 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;
/// Returns the type information of the stored content.
@ -474,6 +477,17 @@ private:
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;
};

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)
{
DynamicAnyHolderImpl<DynamicStruct>* pHolder = dynamic_cast<DynamicAnyHolderImpl<DynamicStruct> *>(_pHolder);
if (pHolder)
return pHolder->operator[](name);
else
throw BadCastException();
return holderImpl<DynamicStruct, InvalidAccessException>("Not an array.")->operator[](name);
}
const DynamicAny& DynamicAny::operator [] (const std::string& name) const
{
const DynamicAnyHolderImpl<DynamicStruct>* pHolder = dynamic_cast<const DynamicAnyHolderImpl<DynamicStruct>* >(_pHolder);
if (pHolder)
return pHolder->operator[](name);
else
throw BadCastException();
return const_cast<const DynamicAny&>(holderImpl<DynamicStruct,
InvalidAccessException>("Not an array.")->operator[](name));
}

View File

@ -47,6 +47,32 @@
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)
{
}
@ -1339,7 +1365,29 @@ void DynamicAnyTest::testULong()
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()
{
DynamicAny any("42");
@ -2207,7 +2255,7 @@ void DynamicAnyTest::testGetIdxMustThrow(DynamicAny& a1, std::vector<DynamicAny>
fail("bad cast - must throw");
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");
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, testFloat);
CppUnit_addTest(pSuite, DynamicAnyTest, testDouble);
CppUnit_addTest(pSuite, DynamicAnyTest, testString);
CppUnit_addTest(pSuite, DynamicAnyTest, testLong);
CppUnit_addTest(pSuite, DynamicAnyTest, testULong);
CppUnit_addTest(pSuite, DynamicAnyTest, testString);
CppUnit_addTest(pSuite, DynamicAnyTest, testUDT);
CppUnit_addTest(pSuite, DynamicAnyTest, testConversionOperator);
CppUnit_addTest(pSuite, DynamicAnyTest, testComparisonOperators);
CppUnit_addTest(pSuite, DynamicAnyTest, testArithmeticOperators);

View File

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

View File

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

View File

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

View File

@ -110,6 +110,12 @@ set DEBUG_SHARED=1
set RELEASE_STATIC=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
for /f %%G in ('findstr /R /V "./." components') do (
if exist %%G (
@ -140,6 +146,7 @@ for /f %%G in ('findstr /R "./." components') do (
)
)
if "%SAMPLES%"=="no" goto :EOF
rem root level component samples