Commit d7357918 authored by thomas.forbriger's avatar thomas.forbriger Committed by thomas.forbriger
Browse files

implemented size-checked type cast for pointers

This is a legacy commit from before 2015-03-01.
It may be incomplete as well as inconsistent.
See COPYING.legacy and README.history for details.


SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 1258
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent f5a67231
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README.changelog,v 1.29 2002-12-31 17:19:46 forbrig Exp $
* $Id: README.changelog,v 1.30 2003-01-03 13:12:17 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -21,12 +21,15 @@
/*! \page page_changelog ChangeLog (AFF)
$Id: README.changelog,v 1.29 2002-12-31 17:19:46 forbrig Exp $
$Id: README.changelog,v 1.30 2003-01-03 13:12:17 forbrig Exp $
\sa \ref page_project_status
Major changes in the interface of the library are marked by \b !!.
- \b 03/01/2003 (thof)
- introduced lib/checkedcast.h and aff::util::SizeCheckedCast
- \b 31/12/2002 (thof)
- NULL is deprecated as pointed out by Wolfgang (replaced by literal 0 in
lib/error.cc and lib/sharedheap_def.h)
......@@ -148,7 +151,7 @@
/*! \page page_project_status Project status (AFF)
$Id: README.changelog,v 1.29 2002-12-31 17:19:46 forbrig Exp $
$Id: README.changelog,v 1.30 2003-01-03 13:12:17 forbrig Exp $
\sa \ref page_changelog
......@@ -215,6 +218,9 @@
<TR><TD>libaff/lib/README</TD>
<TD>has no code</TD><TD>20/12/02</TD><TD>has no code</TD><TD> </TD>
</TR>
<TR><TD>libaff/lib/checkedcast.h</TD>
<TD>03/01/2003</TD><TD>03/01/2003</TD><TD></TD><TD> </TD>
</TR>
<TR><TD>libaff/lib/deepcopy.h</TD>
<TD>29/12/02</TD><TD>29/12/2002</TD><TD>29/12/02</TD><TD> </TD>
</TR>
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: fortranshape.h,v 1.3 2002-12-23 16:43:39 forbrig Exp $
* $Id: fortranshape.h,v 1.4 2003-01-03 13:12:17 forbrig Exp $
* \author Thomas Forbriger
* \date 23/12/2002
*
......@@ -13,6 +13,8 @@
*
* REVISIONS and CHANGES
* - 23/12/2002 V1.0 Thomas Forbriger
* - 03/01/2003 V1.1 (thof)
* - now offers a casted pointer
*
* ============================================================================
*/
......@@ -21,11 +23,12 @@
#ifndef AFF_FORTRANSHAPE_H_VERSION
#define AFF_FORTRANSHAPE_H_VERSION \
"AFF_FORTRANSHAPE_H V1.0 "
"AFF_FORTRANSHAPE_H V1.1"
#define AFF_FORTRANSHAPE_H_CVSID \
"$Id: fortranshape.h,v 1.3 2002-12-23 16:43:39 forbrig Exp $"
"$Id: fortranshape.h,v 1.4 2003-01-03 13:12:17 forbrig Exp $"
#include<aff/array.h>
#include<aff/lib/checkedcast.h>
namespace aff {
......@@ -94,6 +97,8 @@ class FortranArray: private aff::util::FortranShape {
typedef aff::util::FortranShape Tbase;
//! pointer to array base in memory
typedef typename Tarray::Tpointer Tpointer;
//! pointer to array base in memory
typedef typename Tarray::Tvalue Tvalue;
//! create
FortranArray(Tarray array, const bool& BaseOne=true):
Tbase(array.shape(), BaseOne)
......@@ -107,7 +112,18 @@ class FortranArray: private aff::util::FortranShape {
Tbase::last;
Tbase::dimlast;
//@}
//! return pointer to first element in Fortran layout
Tpointer pointer() const { return(Mpointer); }
/*! \brief return type-casted pointer to first element in Fortran layout
*
* The cast checks for const-correctness and type-size. But you have to
* ensure that there is a meaningful relation between both types involved.
*
* \sa aff::util::SizeCheckedCast
*/
template<class TT>
TT* castedpointer() const
{ return(SizeCheckedCast<Tvalue,TT>::cast(Mpointer)); }
private:
//! pointer to memory
Tpointer Mpointer;
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README,v 1.13 2002-12-29 00:09:06 forbrig Exp $
* $Id: README,v 1.14 2003-01-03 13:12:18 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -260,13 +260,11 @@ Aspects to consider:
convert it is via
\code integer* pa=reinterpret_cast<integer *>(fa.pointer()); \endcode
which is a totally unchecked conversion.
We therefore additionally check the type size at runtime by
\code
AFF_assert((sizeof(integer)==sizeof(int)),
"ERROR (f77interface::fill): illegal type size!");
\endcode
Since the type size is known at compile-time, there should be a more
elegant way.
And there is: Have a look at aff::util::SizeCheckedCast. The more recent
version of tests/f77test.cc uses the aff::FortranArray::castedpointer
member template function, which again calls a compile-time size-check.
/*----------------------------------------------------------------------*/
......
/*! \file checkedcast.h
* \brief size checked pointer cast (prototypes)
*
* ----------------------------------------------------------------------------
*
* $Id: checkedcast.h,v 1.1 2003-01-03 13:12:18 forbrig Exp $
* \author Thomas Forbriger
* \date 03/01/2003
*
* size checked pointer cast (prototypes)
*
* \sa aff::util::SizeCheckedCast
*
* Copyright (c) 2003 by Thomas Forbriger (IMG Frankfurt)
*
* REVISIONS and CHANGES
* - 03/01/2003 V1.0 Thomas Forbriger
*
* ============================================================================
*/
// include guard
#ifndef AFF_CHECKEDCAST_H_VERSION
#define AFF_CHECKEDCAST_H_VERSION \
"AFF_CHECKEDCAST_H V1.0"
#define AFF_CHECKEDCAST_H_CVSID \
"$Id: checkedcast.h,v 1.1 2003-01-03 13:12:18 forbrig Exp $"
namespace aff {
namespace util {
/*! \brief utility for compile-time checked cast
*
* Cast a pointer from T* to TT* and check for same size of values of type T
* and TT and for const-correctness of the conversion. Although
* reinterpret_cast should check for conts-correctness, we implement a check
* here too (just for safety - I'm so paranoid, you know).
*
* \sa aff::util::SizeCheckedCast::ConstCheck
* \sa aff::util::SizeCheckedCast::SizeCheck
*
* When exchaning data with Fortran code we have to pass pointers to arrays.
* The f2c.h uses a structure (e.g.) for values of type doublereal that have
* the same memory layout like complex<double> (first a double for the real
* part than a double for the imaginary part) but there is no trivial
* conversion between pointers of these types. Hence we have to use
* reinterpret_cast, which is totally unchecked. With this class we
* implement a cast that checks for matching type-size and const-correctness
* at compile-time. The involved code-overhead is easily optimized away by
* the compiler.
*
* There could be solutions to this problem that involve less code. This
* however is a solution that produces well understandable error messages
* with g++.
*
* Invoking static functions of subclasses in the cast-function may seem
* unnecessary. Indeed, there is a solution of that problem, that relies on
* typedefs to be resolved, which works well with g++. Since I don't know
* about the template instatiation characteristics of other compilers, I
* prefer to force the compiler to instantiate all involved template
* specializations to check whether they support the cast.
*
* \sa aff::FortranArray
* \sa tests/f77test.cc
*
* \param T the input pointer is of type T*
* \param TT the output pointer is of type TT*
*/
template<class T, class TT>
class SizeCheckedCast {
public:
//! return a type-casted (and type-checked) pointer
static TT* cast(T* p) {
return(reinterpret_cast<TT*>(
SizeCheck<sizeof(T),sizeof(TT)>::have_same_size(
ConstCheck<T,TT>::respects_constness(p)))); }
private:
/*! \brief checks for const-correctness of the cast
*
* Only those specializations of this class offer a function
* respects_constness, that represent a const-correct conversion.
*
* The general template if for two non-const types - which is a
* const-correct conversion
*
* \param Tfrom source type (non-const)
* \param Tto destination type (non-const)
*
* \sa aff::util::SizeCheckedCast::ConstCheck<const Tfrom, const Tto>
* \sa aff::util::SizeCheckedCast::ConstCheck<Tfrom, const Tto>
* \sa aff::util::SizeCheckedCast::ConstCheck<const Tfrom, Tto>
* \sa aff::util::SizeCheckedCast
*/
template<class Tfrom, class Tto> class ConstCheck {
public: static T* respects_constness(T* v) { return v; }
}; // class ConstCheck
/*! \brief specialization for const-checked cast
*
* \param Tfrom source type (non-const)
* \param Tto destination type (const)
*
* This conversion is const-correct.
* \sa aff::util::SizeCheckedCast::ConstCheck
* \sa aff::util::SizeCheckedCast
*/
template<class Tfrom, class Tto>
class ConstCheck<Tfrom, const Tto> {
public: static T* respects_constness(T* v) { return v; }
}; // class ConstCheck (specialization)
/*! \brief specialization for const-checked cast
*
* \param Tfrom source type (const)
* \param Tto destination type (const)
*
* This conversion is const-correct.
* \sa aff::util::SizeCheckedCast::ConstCheck
* \sa aff::util::SizeCheckedCast
*/
template<class Tfrom, class Tto>
class ConstCheck<const Tfrom, const Tto> {
public: static T* respects_constness(T* v) { return v; }
}; // class ConstCheck (specialization)
/*! \brief specialization for const-checked cast
*
* \param Tfrom source type (const)
* \param Tto destination type (non-const)
*
* This conversion is \b not const-correct.
* \sa aff::util::SizeCheckedCast::ConstCheck
* \sa aff::util::SizeCheckedCast
*/
template<class Tfrom, class Tto>
class ConstCheck<const Tfrom, Tto>
{ }; // class ConstCheck (specialization)
/*----------------------------------------------------------------*/
/*! \brief checks for matching type-size
*
* The general template (non-matching sizes) does not offer
* a function have_same_size. This function is only offered by the
* specialization that is invoked by conversions for types of same
* size.
*
* \param N size of source type
* \param M size of destination type (N!=M)
*
* \sa aff::util::SizeCheckedCast::SizeCheck<N,N>
* \sa aff::util::SizeCheckedCast
*/
template<int N, int M> class SizeCheck
{ }; // class SizeCheck (specialization)
/*! \brief specialization for type-size checked cast
*
* This specialization is invoked if both types have the same size
* \p N. It thus offers the function have_same_size.
*
* \sa aff::util::SizeCheckedCast::SizeCheck
* \sa aff::util::SizeCheckedCast
*/
template<int N> class SizeCheck<N,N> {
public: static T* have_same_size(T* v) { return v; }
}; // class SizeCheck
}; // class SizeCheckedCast
} // namespace util
} // namespace aff
#endif // AFF_CHECKEDCAST_H_VERSION (includeguard)
/* ----- END OF checkedcast.h ----- */
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: f77interface.cc,v 1.4 2002-12-29 23:02:16 forbrig Exp $
* $Id: f77interface.cc,v 1.5 2003-01-03 13:12:19 forbrig Exp $
* \author Thomas Forbriger
* \date 23/12/2002
*
......@@ -16,13 +16,15 @@
* REVISIONS and CHANGES
* - 23/12/2002 V1.0 Thomas Forbriger
* - 29/12/2002 V1.1 now uses aff::subarray
* - 03/01/2003 V1.2 (thof)
* - use aff::util::SizeCheckedCast
*
* ============================================================================
*/
#define AFF_F77INTERFACE_CC_VERSION \
"AFF_F77INTERFACE_CC V1.1"
"AFF_F77INTERFACE_CC V1.2"
#define AFF_F77INTERFACE_CC_CVSID \
"$Id: f77interface.cc,v 1.4 2002-12-29 23:02:16 forbrig Exp $"
"$Id: f77interface.cc,v 1.5 2003-01-03 13:12:19 forbrig Exp $"
// include assertions
#include<aff/lib/error.h>
......@@ -30,6 +32,7 @@
#include<aff/fortranshape.h>
#include<aff/subarray.h>
#include<aff/shaper.h>
#include<aff/lib/checkedcast.h>
/*----------------------------------------------------------------------*/
......@@ -71,12 +74,7 @@ namespace f77interface {
int fill(const aff::Array<int>& a)
{
aff::FortranArray<int> fa(a);
// that's a critical point
// we need a reinterpret cast to do that!
// for this reason we check the type size
AFF_assert((sizeof(integer)==sizeof(int)),
"ERROR (f77interface::fill): illegal type size!");
integer* pa=reinterpret_cast<integer *>(fa.pointer());
integer* pa=fa.castedpointer<integer>();
integer n1=fa.last(0);
integer n2=fa.last(1);
integer n3=fa.last(2);
......@@ -93,10 +91,8 @@ int fillarray(const aff::Array<float>& v1,
const aff::Array<float>& v2)
{
aff::FortranArray<float> fv1(v1),fv2(v2);
AFF_assert((sizeof(real)==sizeof(float)),
"ERROR (f77interface::fillarray): illegal type size!");
real* p1=reinterpret_cast<real *>(fv1.pointer());
real* p2=reinterpret_cast<real *>(fv2.pointer());
real* p1=fv1.castedpointer<real>();
real* p2=fv2.castedpointer<real>();
integer n1=fv1.last(0);
integer n2=fv2.last(0);
return(fillarray_(p1, p2, &n1, &n2));
......@@ -114,9 +110,7 @@ Tcarray sums()
Tcarray result(maxa);
// prepare Fortran view
aff::FortranArray<Tcvalue> fa(result);
AFF_assert((sizeof(complex)==sizeof(Tcvalue)),
"ERROR (f77interface::sums): illegal type size!");
complex* p=reinterpret_cast<complex *>(fa.pointer());
complex* p=fa.castedpointer<complex>();
integer size;
sums_(p, &maxa, &size);
return(aff::subarray(result)(size));
......@@ -128,11 +122,10 @@ Tcarray sums()
Tzarray viewcommon()
{
typedef Tzarray::Tvalue Tzvalue;
typedef aff::util::SizeCheckedCast<doublecomplex, Tzvalue> Tcast;
integer maxa,maxb;
comdim_(&maxa, &maxb);
AFF_assert((sizeof(doublecomplex)==sizeof(Tzvalue)),
"ERROR (f77interface::viewcommon): illegal type size!");
Tzvalue* p=reinterpret_cast<Tzvalue *>(f77common_.array);
Tzvalue* p=Tcast::cast(f77common_.array);
// create a shape
aff::Strided shape(aff::Shaper(1,f77common_.na,maxa)(1,f77common_.nb,maxb));
// create a representation
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment