/* * Class BitSet Copyright (C) 2019 AleaJactaEst This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Build : scons platform=linux bits=64 */ // #include #include "bitset.h" #define BITSET_SIZE 32 void BitSet::_bind_methods() { ClassDB::bind_method(D_METHOD("size"), &BitSet::size); ClassDB::bind_method(D_METHOD("resize", "num_bits"), &BitSet::resize); ClassDB::bind_method(D_METHOD("clear"), &BitSet::clear); ClassDB::bind_method(D_METHOD("clear_data"), &BitSet::clear_data); ClassDB::bind_method(D_METHOD("set_bit", "bit_number"), &BitSet::set_bit); ClassDB::bind_method(D_METHOD("clear_bit", "bit_number"), &BitSet::clear_bit); ClassDB::bind_method(D_METHOD("write", "bit_number", "value"), &BitSet::write); ClassDB::bind_method(D_METHOD("read", "bit_number"), &BitSet::read); ClassDB::bind_method(D_METHOD("write_serial", "msgout"), &BitSet::write_serial); ClassDB::bind_method(D_METHOD("read_serial", "msgin"), &BitSet::read_serial); ClassDB::bind_method(D_METHOD("show"), &BitSet::show); } BitSet::BitSet() { this->_num_bits = 8; this->_size_byte = 1; this->_mask_last = 0; this->_data = new uint32_t[1]; } BitSet::~BitSet() { // add your cleanup here if ( this->_data != nullptr ) { delete [] this->_data; this->_data = nullptr; } } int BitSet::size() { return this->_size_byte; } #include "core/os/os.h" void BitSet::resize(uint32_t num_bits) { uint32_t n_last_bits; uint32_t new_size_byte = (num_bits + BITSET_SIZE - 1) / BITSET_SIZE; OS::get_singleton()->print((String("INFO [") + String(__FILE__) + String(":") + String(uitos(__LINE__)) + String("] Resize") + String("\n")).utf8()); new_size_byte = (num_bits + BITSET_SIZE - 1) / BITSET_SIZE; if (this->_size_byte != new_size_byte ) { this->_size_byte = new_size_byte; delete [] this->_data; this->_data = new uint32_t[this->_size_byte]; if ( this->_data == nullptr ) { ERR_PRINT("[BitSet::set_bit] Allocation error"); throw "Allocation error"; } } this->_num_bits = num_bits; n_last_bits = this->_num_bits & (BITSET_SIZE - 1); if ( n_last_bits == 0 ) this->_mask_last = ~0; else this->_mask_last = (1 << n_last_bits) - 1; this->clear_data(); } void BitSet::clear() { OS::get_singleton()->print((String("INFO [") + String(__FILE__) + String(":") + String(uitos(__LINE__)) + String("] Clear") + String("\n")).utf8()); this->resize(1); } void BitSet::clear_data() { OS::get_singleton()->print((String("INFO [") + String(__FILE__) + String(":") + String(uitos(__LINE__)) + String("] clear_data") + String("\n")).utf8()); for(uint32_t i = 0;i < this->_size_byte; ++i) this->_data[i] = 0; } void BitSet::set_bit(uint32_t bit_number) { OS::get_singleton()->print((String("INFO [") + String(__FILE__) + String(":") + String(uitos(__LINE__)) + String("] set_bit") + String("\n")).utf8()); if (bit_number >= this->_num_bits) { ERR_PRINTS("[BitSet::set_bit] Out of range (size:" + itos(this->_size_byte) + ", pos:" + itos(bit_number) + ")" ); throw "Out of range"; } uint32_t mask = bit_number & (BITSET_SIZE - 1); mask = 1 << mask; this->_data[bit_number>>5] |= mask; } void BitSet::clear_bit(uint32_t bit_number) { OS::get_singleton()->print((String("INFO [") + String(__FILE__) + String(":") + String(uitos(__LINE__)) + String("] clear_bit") + String("\n")).utf8()); if (bit_number >= this->_num_bits) { ERR_PRINTS("[BitSet::clear_bit] Out of range (size:" + itos(this->_size_byte) + ", pos:" + itos(bit_number) + ")" ); throw "Out of range"; } uint32_t mask = bit_number & (BITSET_SIZE - 1); mask = 1 << mask; this->_data[bit_number>>5] &= ~ mask; } void BitSet::write(uint32_t bit_number, bool value) { if (bit_number >= this->_num_bits) { ERR_PRINTS("[BitSet::put] Out of range (size:" + itos(this->_size_byte) + ", pos:" + itos(bit_number) + ")" ); throw "Out of range"; } if ( value == true ) this->set_bit(bit_number); else this->clear_bit(bit_number); } bool BitSet::read(uint32_t bit_number) { if (bit_number >= this->_num_bits) { ERR_PRINTS("[BitSet::pull] Out of range (size:" + itos(this->_size_byte) + ", pos:" + itos(bit_number) + ")" ); throw "Out of range"; } uint32_t mask = bit_number & (BITSET_SIZE - 1); mask = 1 << mask; return (this->_data[bit_number>>5] & mask) != 0; } void BitSet::write_serial(Ref msgout) { uint8_t current_version = 0; msgout->put_uint8(current_version); msgout->put_uint32(this->_num_bits); // _size_byte est lié à _num_bits dommage que l'on envoie celui-la msgout->put_uint32(this->_size_byte); for(uint32_t i = 0;i < this->_size_byte; ++i) msgout->put_uint32(this->_data[i]); } void BitSet::read_serial(Ref msgin) { uint8_t current_version = msgin->get_sint8(); uint8_t num_bits; switch ( current_version ) { case 0: num_bits = msgin->get_uint32(); this->resize(num_bits); for(uint32_t i = 0;i < this->_size_byte; ++i) this->_data[i] = msgin->get_uint32(); break; default: ERR_PRINTS("[BitSet::read_serial] Unknown version: " + itos(current_version)); throw "Unknown version"; break; } } String BitSet::show() { Ref msgout; msgout.instance(); this->write_serial(msgout); return msgout->show(); }