194 lines
6.1 KiB
C++
194 lines
6.1 KiB
C++
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
Build :
|
|
scons platform=linux bits=64
|
|
|
|
*/
|
|
|
|
// #include <iostream>
|
|
#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_PRINT("[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_PRINT("[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_PRINT("[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_PRINT("[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<BitStream> 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<BitStream> 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_PRINT("[BitSet::read_serial] Unknown version: " + itos(current_version));
|
|
throw "Unknown version";
|
|
break;
|
|
}
|
|
}
|
|
|
|
String BitSet::show()
|
|
{
|
|
Ref<BitStream> msgout;
|
|
msgout.instance();
|
|
this->write_serial(msgout);
|
|
return msgout->show();
|
|
}
|