ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/DataStorage/valuearray_base.cpp

Go to the documentation of this file.
00001 #ifdef _MSC_VER
00002 #define NOMINMAX 1
00003 #endif
00004 
00005 #include "valuearray_base.hpp"
00006 #include "valuearray_converter.hpp"
00007 #include "common.hpp"
00008 
00009 namespace isis
00010 {
00011 namespace data
00012 {
00013 
00020 scaling_pair ValueArrayBase::getScaling( const scaling_pair &scaling, short unsigned int ID )const
00021 {
00022     if( scaling.first.isEmpty() || scaling.second.isEmpty() )
00023         return getScalingTo( ID );
00024     else
00025         return scaling;
00026 }
00027 
00028 ValueArrayBase::ValueArrayBase( size_t length ): m_len( length ) {}
00029 
00030 size_t ValueArrayBase::getLength() const { return m_len;}
00031 
00032 ValueArrayBase::~ValueArrayBase() {}
00033 
00034 ValueArrayBase::DelProxy::DelProxy( const isis::data::ValueArrayBase &master ): boost::shared_ptr<const void>( master.getRawAddress() )
00035 {
00036     LOG( Debug, verbose_info ) << "Creating DelProxy for " << master.getTypeName() << " at " << this->get();
00037 }
00038 
00039 void ValueArrayBase::DelProxy::operator()( const void *at )
00040 {
00041     LOG( Debug, verbose_info )
00042             << "Deletion for " << this->get() << " called from proxy at offset "
00043             << static_cast<const uint8_t *>( at ) - static_cast<const uint8_t *>( this->get() )
00044             << ", current use_count: " << this->use_count();
00045     this->reset();//actually not needed, but we keep it here to keep obfuscation low
00046 }
00047 
00048 
00049 const _internal::ValueArrayConverterMap &ValueArrayBase::converters()
00050 {
00051     static _internal::ValueArrayConverterMap ret; //@todo not using class Singleton because ValueArrayConverterMap is hidden
00052     return ret;
00053 }
00054 
00055 const ValueArrayBase::Converter &ValueArrayBase::getConverterTo( unsigned short ID )const
00056 {
00057     const _internal::ValueArrayConverterMap::const_iterator f1 = converters().find( getTypeID() );
00058     LOG_IF( f1 == converters().end(), Debug, error ) << "There is no known conversion from " << util::getTypeMap()[getTypeID()];
00059     const _internal::ValueArrayConverterMap::mapped_type::const_iterator f2 = f1->second.find( ID );
00060     LOG_IF( f2 == f1->second.end(), Debug, error ) << "There is no known conversion from " << util::getTypeMap()[getTypeID()] << " to " << util::getTypeMap()[ID];
00061     return f2->second;
00062 }
00063 
00064 size_t ValueArrayBase::compare( size_t start, size_t end, const ValueArrayBase &dst, size_t dst_start ) const
00065 {
00066     assert( start <= end );
00067     size_t ret = 0;
00068     size_t _length = end - start;
00069 
00070     if ( dst.getTypeID() != getTypeID() ) {
00071         LOG( Debug, error )
00072                 << "Comparing to a ValueArray of different type(" << dst.getTypeName() << ", not " << getTypeName()
00073                 << "). Assuming all voxels to be different";
00074         return _length;
00075     }
00076 
00077     LOG_IF( end >= getLength(), Runtime, error )
00078             << "End of the range (" << end << ") is behind the end of this ValueArray (" << getLength() << ")";
00079     LOG_IF( _length + dst_start >= dst.getLength(), Runtime, error )
00080             << "End of the range (" << _length + dst_start << ") is behind the end of the destination (" << dst.getLength() << ")";
00081 
00082     // lock the memory so we can mem-compare the elements (use uint8_t because some compilers do not like arith on void*)
00083     const boost::shared_ptr<const uint8_t>
00084     src_s = boost::static_pointer_cast<const uint8_t>( getRawAddress() ),
00085     dst_s = boost::static_pointer_cast<const uint8_t>( dst.getRawAddress() );
00086     const uint8_t *src_p = src_s.get(), *dst_p = dst_s.get();
00087     const size_t el_size = bytesPerElem();
00088 
00089     for ( size_t i = start; i < end; i++ ) {
00090         if ( memcmp( src_p + ( i * el_size ), dst_p + ( i * el_size ), el_size ) != 0 )
00091             ret++;
00092     }
00093 
00094     return ret;
00095 }
00096 
00097 
00098 ValueArrayBase::Reference ValueArrayBase::copyByID( unsigned short ID, scaling_pair scaling ) const
00099 {
00100     if( !ID )ID = getTypeID();
00101 
00102     const Converter &conv = getConverterTo( ID );
00103 
00104     if( conv ) {
00105         boost::scoped_ptr<ValueArrayBase> ret;
00106         conv->generate( *this, ret, getScaling( scaling, ID ) );
00107         return *ret;
00108     } else {
00109         LOG( Runtime, error )
00110                 << "I dont know any conversion from "
00111                 << util::MSubject( getTypeName() ) << " to " << util::MSubject( util::getTypeMap( false, true )[ID] );
00112         return Reference(); // return an empty Reference
00113     }
00114 }
00115 
00116 bool ValueArrayBase::copyTo( isis::data::ValueArrayBase &dst, scaling_pair scaling ) const
00117 {
00118     const unsigned short dID = dst.getTypeID();
00119     const Converter &conv = getConverterTo( dID );
00120 
00121     if( conv ) {
00122         conv->convert( *this, dst, getScaling( scaling, dID ) );
00123         return true;
00124     } else {
00125         LOG( Runtime, error ) << "I dont know any conversion from " << util::MSubject( toString( true ) ) << " to " << dst.getTypeName();
00126         return false;
00127     }
00128 }
00129 
00130 
00131 ValueArrayBase::Reference ValueArrayBase::createByID( unsigned short ID, size_t len )
00132 {
00133     const _internal::ValueArrayConverterMap::const_iterator f1 = converters().find( ID );
00134     _internal::ValueArrayConverterMap::mapped_type::const_iterator f2;
00135 
00136     // try to get a converter to convert the requestet type into itself - they 're there for all known types
00137     if( f1 != converters().end() && ( f2 = f1->second.find( ID ) ) != f1->second.end() ) {
00138         const _internal::ValueArrayConverterBase &conv = *( f2->second );
00139         boost::scoped_ptr<ValueArrayBase> ret;
00140         conv.create( ret, len );
00141         return *ret;
00142     } else {
00143         LOG( Debug, error ) << "There is no known creator for " << util::getTypeMap()[ID];
00144         return Reference(); // return an empty Reference
00145     }
00146 }
00147 
00148 ValueArrayBase::Reference ValueArrayBase::convertByID( short unsigned int ID, scaling_pair scaling )
00149 {
00150     scaling = getScaling( scaling, ID );
00151     static const util::Value<uint8_t> one( 1 );
00152     static const util::Value<uint8_t> zero( 0 );
00153 
00154     if( scaling.first->eq( one ) && scaling.second->eq( zero ) && getTypeID() == ID ) { // if type is the same and scaling is 1/0
00155         return *this; //cheap copy
00156     } else {
00157         return copyByID( ID, scaling ); // convert into new
00158     }
00159 }
00160 
00161 ValueArrayBase::Reference ValueArrayBase::cloneToNew( size_t length ) const
00162 {
00163     return createByID( getTypeID(), length );
00164 }
00165 
00166 
00167 void ValueArrayBase::copyRange( size_t start, size_t end, ValueArrayBase &dst, size_t dst_start )const
00168 {
00169     assert( start <= end );
00170     const size_t len = end - start + 1;
00171     LOG_IF( ! dst.isSameType( *this ), Debug, error )
00172             << "Range copy into a ValueArray of different type is not supportet. Its " << dst.getTypeName() << " not " << getTypeName();
00173 
00174     if( end >= getLength() ) {
00175         LOG( Runtime, error )
00176                 << "End of the range (" << end << ") is behind the end of this ValueArray (" << getLength() << ")";
00177     } else if( len + dst_start > dst.getLength() ) {
00178         LOG( Runtime, error )
00179                 << "End of the range (" << len + dst_start << ") is behind the end of the destination (" << dst.getLength() << ")";
00180     } else {
00181         boost::shared_ptr<void> daddr = dst.getRawAddress();
00182         const boost::shared_ptr<const void> saddr = getRawAddress();
00183         const size_t soffset = bytesPerElem() * start; //source offset in bytes
00184         const int8_t *const  src = ( int8_t * )saddr.get();
00185         const size_t doffset = bytesPerElem() * dst_start;//destination offset in bytes
00186         int8_t *const  dest = ( int8_t * )daddr.get();
00187         const size_t blength = len * bytesPerElem();//length in bytes
00188         memcpy( dest + doffset, src + soffset, blength );
00189     }
00190 }
00191 
00192 scaling_pair ValueArrayBase::getScalingTo( unsigned short typeID, const std::pair<util::ValueReference, util::ValueReference> &minmax, autoscaleOption scaleopt )const
00193 {
00194     LOG_IF( minmax.first.isEmpty() || minmax.second.isEmpty(), Debug, error ) << "One of the ValueReference's in minmax is empty(). This will crash...";
00195     const Converter &conv = getConverterTo( typeID );
00196 
00197     if ( conv ) {
00198         return conv->getScaling( *minmax.first, *minmax.second, scaleopt );
00199     } else {
00200         LOG( Runtime, error )
00201                 << "I dont know any conversion from " << util::MSubject( getTypeName() ) << " to " << util::MSubject( util::getTypeMap( false, true )[typeID] );
00202         return scaling_pair();
00203     }
00204 }
00205 size_t ValueArrayBase::useCount() const
00206 {
00207     return getRawAddress().use_count();
00208 }
00209 ValueArrayBase::value_iterator ValueArrayBase::endGeneric()
00210 {
00211     return beginGeneric() + m_len;
00212 }
00213 ValueArrayBase::const_value_iterator ValueArrayBase::endGeneric()const
00214 {
00215     return beginGeneric() + m_len;
00216 }
00217 
00219 namespace _internal
00220 {
00221 template<> GenericValueIterator<true>::reference GenericValueIterator<true>::operator*() const
00222 {
00223     assert( getValueFunc );
00224     return ConstValueAdapter( p, getValueFunc );
00225 }
00226 template<> GenericValueIterator<false>::reference GenericValueIterator<false>::operator*() const
00227 {
00228     assert( getValueFunc );
00229     return WritingValueAdapter( p, getValueFunc, setValueFunc );
00230 }
00231 
00232 ConstValueAdapter::ConstValueAdapter( const uint8_t *const _p, Getter _getValueFunc ): util::ValueReference( _getValueFunc( _p ) ), p( _p ) {}
00233 bool ConstValueAdapter::operator==( const util::ValueReference &val )const {return ( *this )->eq( *val );}
00234 bool ConstValueAdapter::operator!=( const util::ValueReference &val )const {return !operator==( val );}
00235 
00236 bool ConstValueAdapter::operator<( const util::ValueReference &val )const {return ( *this )->lt( *val );}
00237 bool ConstValueAdapter::operator>( const util::ValueReference &val )const {return ( *this )->gt( *val );}
00238 
00239 WritingValueAdapter::WritingValueAdapter( uint8_t *const _p, Getter _getValueFunc, Setter _setValueFunc ): ConstValueAdapter( _p, _getValueFunc ), setValueFunc( _setValueFunc ) {}
00240 WritingValueAdapter WritingValueAdapter::operator=( const util::ValueReference &val )
00241 {
00242     assert( setValueFunc );
00243     setValueFunc( const_cast<uint8_t * const>( p ), *val );
00244     return *this;
00245 }
00246 } // namespace _internal
00248 }
00249 }