00001 #include "UTIL/BitField64.h"
00002
00003 #include <cmath>
00004 #include <algorithm>
00005
00006 using namespace EVENT ;
00007
00008 namespace UTIL{
00009
00010
00011 BitFieldValue::BitFieldValue( lcio::long64& bitfield, const std::string& name,
00012 unsigned offset, int signedWidth ) :
00013 _b(bitfield),
00014 _mask(0),
00015 _name( name ),
00016 _offset( offset ),
00017 _width( abs( signedWidth ) ),
00018 _minVal(0),
00019 _maxVal(0),
00020 _isSigned( signedWidth < 0 ) {
00021
00022
00023 if( offset < 0 || offset > 63 || offset+_width > 64 ) {
00024
00025 std::stringstream s ;
00026 s << " BitFieldValue: out of range - offset : "
00027 << offset << " width " << _width ;
00028
00029 throw( Exception( s.str() ) ) ;
00030 }
00031
00032 _mask = ( ( 0x0001LL << _width ) - 1 ) << offset ;
00033
00034
00035
00036 if( _isSigned ){
00037
00038 _minVal = ( 1LL << ( _width - 1 ) ) - ( 1LL << _width ) ;
00039 _maxVal = ( 1LL << ( _width - 1 ) ) - 1 ;
00040
00041 } else {
00042
00043 _maxVal = 0x0001<<_width ;
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053 }
00054
00055
00056 long64 BitFieldValue::value() const {
00057
00058 if( _isSigned ) {
00059
00060 long64 val = ( _b & _mask ) >> _offset ;
00061
00062 if( ( val & ( 1LL << ( _width - 1 ) ) ) != 0 ) {
00063
00064 val -= ( 1LL << _width );
00065 }
00066
00067 return val ;
00068
00069 } else {
00070
00071 return ( _b & _mask ) >> _offset ;
00072 }
00073 }
00074
00075 BitFieldValue& BitFieldValue::operator=(long64 in) {
00076
00077
00078 if( in < _minVal || in > _maxVal ) {
00079
00080 std::stringstream s ;
00081 s << " BitFieldValue: out of range : " << in
00082 << " for width " << _width ;
00083
00084 throw( Exception( s.str() ) );
00085 }
00086
00087 _b &= ~_mask ;
00088
00089 _b |= ( ( in << _offset ) & _mask ) ;
00090
00091 return *this ;
00092 }
00093
00094
00095
00096
00097 size_t BitField64::index( const std::string& name) const {
00098
00099 IndexMap::const_iterator it = _map.find( name ) ;
00100
00101 if( it != _map.end() )
00102
00103 return it->second ;
00104
00105 else
00106 throw Exception(" BitFieldValue: unknown name: " + name ) ;
00107 }
00108
00109 unsigned BitField64::highestBit() {
00110
00111 unsigned hb(0) ;
00112
00113 for(unsigned i=0;i<_fields.size();i++){
00114
00115 if( hb < ( _fields[i]->offset() + _fields[i]->width() ) )
00116 hb = _fields[i]->offset() + _fields[i]->width() ;
00117 }
00118 return hb ;
00119 }
00120
00121
00122 std::string BitField64::valueString() const {
00123
00124 std::stringstream os ;
00125
00126 for(unsigned i=0;i<_fields.size();i++){
00127
00128 if( i != 0 ) os << "," ;
00129
00130 os << _fields[i]->name() << ":" << _fields[i]->value() ;
00131
00132 }
00133 return os.str() ;
00134 }
00135
00136 std::string BitField64::fieldDescription() const {
00137
00138 std::stringstream os ;
00139
00140 for(unsigned i=0;i<_fields.size();i++){
00141
00142 if( i != 0 ) os << "," ;
00143
00144 os << _fields[i]->name() << ":"
00145 << _fields[i]->offset() << ":" ;
00146
00147 if( _fields[i]->isSigned() )
00148 os << "-" ;
00149
00150 os << _fields[i]->width() ;
00151
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 return os.str() ;
00170 }
00171
00172 void BitField64::addField( const std::string& name, unsigned offset, int width ){
00173
00174
00175 BitFieldValue* bfv = new BitFieldValue( _value, name, offset, width ) ;
00176
00177 _fields.push_back( bfv ) ;
00178
00179 _map[ name ] = _fields.size()-1 ;
00180
00181 if( _joined & bfv->mask() ) {
00182
00183 std::stringstream s ;
00184 s << " BitFieldValue: bits already used " << std::hex << _joined
00185 << " for mask " << bfv->mask() ;
00186
00187 throw( Exception( s.str() ) ) ;
00188
00189 }
00190
00191 _joined |= _fields.back()->mask() ;
00192
00193 }
00194
00195 void BitField64::init( const std::string& initString) {
00196
00197 unsigned offset = 0 ;
00198
00199
00200 std::vector<std::string> fieldDescriptors ;
00201 LCTokenizer t( fieldDescriptors ,',') ;
00202
00203 std::for_each( initString.begin(), initString.end(), t ) ;
00204
00205 for(unsigned i=0; i< fieldDescriptors.size() ; i++ ){
00206
00207 std::vector<std::string> subfields ;
00208 LCTokenizer ts( subfields ,':') ;
00209
00210 std::for_each( fieldDescriptors[i].begin(), fieldDescriptors[i].end(), ts );
00211
00212 std::string name ;
00213 int width ;
00214 unsigned thisOffset ;
00215
00216 switch( subfields.size() ){
00217
00218 case 2:
00219
00220 name = subfields[0] ;
00221 width = atol( subfields[1].c_str() ) ;
00222 thisOffset = offset ;
00223
00224 offset += abs( width ) ;
00225
00226 break ;
00227
00228 case 3:
00229 name = subfields[0] ;
00230 thisOffset = atol( subfields[1].c_str() ) ;
00231 width = atol( subfields[2].c_str() ) ;
00232
00233 offset = thisOffset + abs( width ) ;
00234
00235 break ;
00236
00237 default:
00238
00239 std::stringstream s ;
00240 s << " BitField64: invalid number of subfields "
00241 << fieldDescriptors[i] ;
00242
00243 throw( Exception( s.str() ) ) ;
00244 }
00245
00246 addField( name , thisOffset, width ) ;
00247 }
00248 }
00249
00250
00251 std::ostream& operator<<(std::ostream& os, const BitField64& b){
00252
00253 os << " bitfield: 0x" << std::hex
00254 << b._value << std::dec << std::endl ;
00255
00256 for( BitField64::IndexMap::const_iterator it = b._map.begin() ;
00257 it != b._map.end() ; ++it ){
00258
00259 os << " " << it->first << " [" << b[ it->second ].offset() << ":" ;
00260
00261 if( b[ it->second ].isSigned() ) os << "-" ;
00262
00263 os << b[ it->second ].width() << "] : " ;
00264
00265
00266 os << b[ it->second ].value()
00267 << std::endl ;
00268
00269 }
00270
00271 return os ;
00272 }
00273
00274 }
00275