ISIS Core Library 0.7.2 (api 3.0.0)
|
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 }