File indexing completed on 2026-04-09 07:49:31
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <vector>
0018 #include <string>
0019 #include <cstring>
0020 #include <cstdint>
0021 #include <sstream>
0022 #include <iomanip>
0023
0024 #include "sstr.h"
0025 #include "ssys.h"
0026 #include "SName.h"
0027
0028
0029 struct SBitSet
0030 {
0031 static std::string Brief( const SBitSet* elv, const SName* id );
0032
0033 template<typename T>
0034 static T Value( unsigned num_bits, const char* ekey, const char* fallback );
0035
0036 template<typename T>
0037 static T Value( unsigned num_bits, const char* spec );
0038
0039
0040 static SBitSet* Create( unsigned num_bits, const char* ekey, const char* fallback );
0041 static SBitSet* Create( unsigned num_bits, const char* spec);
0042
0043
0044 template<typename T>
0045 static SBitSet* Create(T value);
0046
0047
0048 static int ParseSpec( unsigned num_bits, bool* bits , const char* spec, bool dump );
0049
0050 template<typename T>
0051 static void ParseValue( unsigned num_bits, bool* bits , T value );
0052
0053 template<typename T>
0054 static bool IsSet( T value, int ibit );
0055
0056
0057 static std::string Desc( unsigned num_bits, const bool* bits, bool reverse );
0058
0059 template<typename T>
0060 static std::string DescValue( T val );
0061
0062
0063 static constexpr const char* __level = "SBitSet__level" ;
0064 int level ;
0065 unsigned num_bits ;
0066 bool* bits ;
0067
0068
0069 const char* label ;
0070 const char* spec ;
0071
0072
0073 SBitSet( unsigned num_bits);
0074 virtual ~SBitSet();
0075
0076 void set_label(const char* label);
0077 void set_spec( const char* spec);
0078
0079 void set(bool all);
0080 void parse_spec( const char* spec);
0081
0082
0083
0084 template<typename T>
0085 void parse_value( T value);
0086
0087 bool is_set(unsigned pos) const ;
0088
0089 unsigned count() const ;
0090 bool is_all_set() const ;
0091 bool all() const ;
0092 bool any() const ;
0093 bool none() const ;
0094
0095
0096 void get_pos( std::vector<unsigned>& pos, bool value ) const ;
0097
0098 std::string desc() const ;
0099
0100 template<typename T>
0101 T value() const ;
0102
0103
0104 void serialize(std::vector<unsigned char>& buf) const ;
0105 static SBitSet* CreateFromBytes(const std::vector<unsigned char>& bytes);
0106 int compare(const SBitSet* other) const ;
0107
0108 };
0109
0110
0111 inline std::string SBitSet::Brief( const SBitSet* elv, const SName* id )
0112 {
0113 std::stringstream ss ;
0114 ss << "SBitSet::Brief" ;
0115 std::string str = ss.str();
0116 return str ;
0117 }
0118
0119
0120
0121 template<typename T>
0122 inline T SBitSet::Value( unsigned num_bits, const char* ekey, const char* fallback )
0123 {
0124 SBitSet* bs = Create(num_bits, ekey, fallback);
0125 T val = bs->value<T>() ;
0126 delete bs ;
0127 return val ;
0128 }
0129
0130 template<typename T>
0131 inline T SBitSet::Value( unsigned num_bits, const char* spec )
0132 {
0133 SBitSet* bs = Create(num_bits, spec);
0134 T val = bs->value<T>() ;
0135 delete bs ;
0136 return val ;
0137 }
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 inline SBitSet* SBitSet::Create(unsigned num_bits, const char* ekey, const char* fallback )
0155 {
0156 const char* spec = ssys::getenvvar(ekey, fallback) ;
0157 SBitSet* bs = Create(num_bits, spec );
0158 if(bs) bs->set_label(ekey);
0159 return bs ;
0160 }
0161
0162 inline SBitSet* SBitSet::Create(unsigned num_bits, const char* spec )
0163 {
0164 SBitSet* bs = nullptr ;
0165 if(spec)
0166 {
0167 bs = new SBitSet(num_bits);
0168 bs->parse_spec(spec);
0169 }
0170 return bs ;
0171 }
0172
0173
0174 template<typename T>
0175 inline SBitSet* SBitSet::Create(T value)
0176 {
0177 unsigned _num_bits = 8*sizeof(T);
0178 SBitSet* bs = new SBitSet(_num_bits);
0179 bs->parse_value(value);
0180 return bs ;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 inline int SBitSet::ParseSpec( unsigned num_bits, bool* bits, const char* spec, bool dump )
0234 {
0235 bool with_complement = strlen(spec) > 0 && ( spec[0] == '~' || spec[0] == 't' ) ;
0236 for(unsigned i=0 ; i < num_bits ; i++) bits[i] = with_complement ? true : false ;
0237
0238 bool with_colon = strlen(spec) >= 2 && spec[1] == ':' ;
0239
0240 int post_complement = with_complement ? 1 : 0 ;
0241 int post_colon = with_colon ? 1 : 0 ;
0242 const char* spec_ = spec + post_complement + post_colon ;
0243
0244
0245
0246 if(dump) std::cout
0247 << "[SBitSet::ParseSpec\n"
0248 << " dump " << ( dump ? "YES" : "NO " )
0249 << " num_bits " << num_bits << "\n"
0250 << " spec [" << ( spec ? spec : "-" ) << "]" << "\n"
0251 << " spec_[" << ( spec_ ? spec_ : "-" ) << "]" << "\n"
0252 << " with_complement " << ( with_complement ? "YES" : "NO " ) << "\n"
0253 << " with_colon " << ( with_colon ? "YES" : "NO " ) << "\n"
0254 << "\n"
0255 ;
0256
0257 std::vector<int> pos ;
0258 char delim = ',' ;
0259 sstr::split<int>( pos, spec_ , delim );
0260
0261 int rc = 0;
0262
0263 for(unsigned i=0 ; i < pos.size() ; i++)
0264 {
0265 int ipos = pos[i] ;
0266 int upos_ = ipos < 0 ? ipos + num_bits : ipos ;
0267
0268 assert( upos_ > -1 );
0269
0270 unsigned upos = upos_ ;
0271 bool in_range = upos < num_bits ;
0272 if(!in_range) std::cerr
0273 << "-SBitSet::ParseSpec"
0274 << " i " << i
0275 << " pos.size " << pos.size()
0276 << " ipos " << ipos
0277 << " upos_ " << upos_
0278 << " upos " << upos
0279 << " num_bits " << num_bits
0280 << " in_range " << ( in_range ? "YES" : "NO " )
0281 << "\n"
0282 ;
0283
0284
0285 if(!in_range) rc += 1 ;
0286
0287
0288 if(upos < num_bits) bits[upos] = with_complement ? false : true ;
0289 }
0290
0291 if(dump) std::cout
0292 << " rc " << rc
0293 << "]SBitSet::ParseSpec\n"
0294 ;
0295
0296 return rc;
0297
0298 }
0299
0300
0301
0302
0303
0304 template<typename T>
0305 inline void SBitSet::ParseValue( unsigned num_bits, bool* bits, T value )
0306 {
0307 assert( sizeof(T)*8 == num_bits );
0308 for(unsigned i=0 ; i < num_bits ; i++ ) bits[i] = IsSet(value, i) ;
0309 }
0310
0311 template<typename T>
0312 inline bool SBitSet::IsSet( T value, int _ibit )
0313 {
0314 unsigned num_bits = sizeof(T)*8 ;
0315 T ibit = _ibit < 0 ? _ibit + num_bits : _ibit ;
0316 T mask = 0x1 << ibit ;
0317 bool is_set = ( value & mask ) != 0 ;
0318 return is_set ;
0319 }
0320
0321
0322
0323 inline std::string SBitSet::Desc( unsigned num_bits, const bool* bits, bool reverse )
0324 {
0325 std::stringstream ss ;
0326 ss << std::setw(4) << num_bits << " : " ;
0327 for(unsigned i=0 ; i < num_bits ; i++) ss << ( bits[reverse ? num_bits - 1 - i : i ] ? "1" : "0" ) ;
0328 std::string str = ss.str();
0329 return str ;
0330 }
0331
0332 template<typename T>
0333 inline std::string SBitSet::DescValue( T val )
0334 {
0335 std::stringstream ss ;
0336 ss << "bs.0x" << std::hex << val << std::dec ;
0337 std::string str = ss.str();
0338 return str ;
0339 }
0340
0341
0342
0343 inline bool SBitSet::is_set(unsigned pos) const
0344 {
0345 assert( pos < num_bits );
0346 return bits[pos] ;
0347 }
0348
0349 inline unsigned SBitSet::count() const
0350 {
0351 unsigned num = 0 ;
0352 for(unsigned i=0 ; i < num_bits ; i++ ) if(bits[i]) num += 1 ;
0353 return num ;
0354 }
0355
0356 inline bool SBitSet::is_all_set() const { return all() ; }
0357 inline bool SBitSet::all() const { return count() == num_bits ; }
0358 inline bool SBitSet::any() const { return count() > 0 ; }
0359 inline bool SBitSet::none() const { return count() == 0 ; }
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 inline void SBitSet::get_pos( std::vector<unsigned>& pos, bool value) const
0370 {
0371 for(unsigned i=0 ; i < num_bits ; i++ ) if(bits[i] == value) pos.push_back(i) ;
0372 }
0373
0374 inline SBitSet::SBitSet( unsigned num_bits_ )
0375 :
0376 level(ssys::getenvint(__level,0)),
0377 num_bits(num_bits_),
0378 bits(new bool[num_bits]),
0379 label(nullptr),
0380 spec(nullptr)
0381 {
0382 set(false);
0383 }
0384
0385 inline void SBitSet::set_label(const char* label_)
0386 {
0387 label = strdup(label_);
0388 }
0389 inline void SBitSet::set_spec( const char* spec_)
0390 {
0391 spec = strdup(spec_);
0392 }
0393
0394
0395 inline void SBitSet::set(bool all)
0396 {
0397 for(unsigned i=0 ; i < num_bits ; i++ ) bits[i] = all ;
0398 }
0399
0400
0401 inline void SBitSet::parse_spec(const char* spec)
0402 {
0403 bool dump = level > 0 ;
0404 ParseSpec(num_bits, bits, spec, dump);
0405 set_spec(spec);
0406 }
0407
0408 template<typename T>
0409 inline void SBitSet::parse_value(T value)
0410 {
0411 ParseValue(num_bits, bits, value);
0412 }
0413
0414
0415
0416
0417 inline SBitSet::~SBitSet()
0418 {
0419 delete [] bits ;
0420 }
0421
0422 inline std::string SBitSet::desc() const
0423 {
0424 std::stringstream ss ;
0425 ss
0426 << std::setw(4) << ( label ? label : "-" )
0427 << std::setw(10) << ( spec ? spec : "-" )
0428 << Desc(num_bits, bits, false)
0429 ;
0430
0431 std::string s = ss.str();
0432 return s ;
0433 }
0434
0435
0436 template<typename T>
0437 inline T SBitSet::value() const
0438 {
0439 T val = 0 ;
0440 for(unsigned i=0 ; i < num_bits ; i++ )
0441 {
0442 if(bits[i]) val |= ( 0x1 << i ) ;
0443 }
0444 return val ;
0445 }
0446
0447
0448 inline void SBitSet::serialize(std::vector<unsigned char>& bytes) const
0449 {
0450 int num_bytes = (num_bits + 7)/8 ;
0451 bytes.resize(num_bytes, 0);
0452 for (size_t i = 0; i < num_bits; ++i) if(bits[i]) bytes[i/8] |= (1 << (i % 8));
0453 }
0454
0455 inline SBitSet* SBitSet::CreateFromBytes(const std::vector<unsigned char>& bytes)
0456 {
0457 int num_bits = 8*bytes.size() ;
0458 SBitSet* bs = new SBitSet(num_bits);
0459 for (int i = 0; i < num_bits; ++i)
0460 {
0461 unsigned mask = 0x1 << (i % 8) ;
0462 unsigned char byte = bytes[i/8] ;
0463 bs->bits[i] = byte & mask ;
0464 }
0465 return bs ;
0466 }
0467
0468 inline int SBitSet::compare(const SBitSet* other) const
0469 {
0470 if(!other) return -1 ;
0471 if(num_bits != other->num_bits) return -2 ;
0472 int diff = 0 ;
0473 for(unsigned i=0 ; i < num_bits ; i++) diff += ( bits[i] == other->bits[i] ? 0 : 1 ) ;
0474 return diff ;
0475 }
0476
0477