diff --git a/corsika/detail/framework/utility/BitField.inl b/corsika/detail/framework/utility/BitField.inl new file mode 100644 index 0000000000000000000000000000000000000000..8ed20db85640c391114881bc27c72a3727dbbcb3 --- /dev/null +++ b/corsika/detail/framework/utility/BitField.inl @@ -0,0 +1,74 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +namespace corsika { + + template <typename TType> + BitField<TType>::BitField(TType& target) + : target_(target) {} + + template <typename TType> + typename BitField<TType>::Bit BitField<TType>::operator[](unsigned int position) { + return Bit(target_, TType(1) << position); + } + + template <typename TType> + typename BitField<TType>::Bit BitField<TType>::at(unsigned int position) { + if (position >= 8 * sizeof(TType)) + // throw std::exceptionOutOfBoundException("Running out of bits."); + throw std::exception("Running out of bits."); + return (*this)[position]; + } + + template <typename TType> + template <typename TMask> + BitField<TType>& BitField<TType>::mask(const TMask mask, const bool value) { + Bit(target_, mask) = value; + return *this; + } + + template <typename TType> + template <typename TMask> + TType BitField<TType>::get(const TMask mask) { + return target_ & TType(mask); + } + + // Nested Bit class: + template <typename TType> + BitField<TType>::Bit::Bit(TType& target, TType mask) + : target_(target) + , mask_(mask) {} + + template <typename TType> + BitField<TType>::Bit::operator bool() const { + return static_cast<bool>(target_ & mask_); + } + + template <typename TType> + bool BitField<TType>::Bit::operator~() const { + return !static_cast<bool>(*this); + } + + template <typename TType> + typename BitField<TType>::Bit& BitField<TType>::Bit::operator=(const bool value) { + if (value) + target_ |= mask_; + else + target_ &= ~mask_; + return *this; + } + + template <typename TType> + typename BitField<TType>::Bit& BitField<TType>::Bit::flip() { + return *this = ~(*this); + } +} // namespace corsika \ No newline at end of file diff --git a/corsika/framework/utility/BitField.hpp b/corsika/framework/utility/BitField.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ef7f40719d1f101ed8e0fc359445d8b515a43cb1 --- /dev/null +++ b/corsika/framework/utility/BitField.hpp @@ -0,0 +1,69 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +/** + \author Hans Dembinski + \author Lukas Nellen + \author Darko Veberic + \date 27 Jan 2014 + + \version $Id: Bit.h 25126 2014-02-03 22:13:10Z darko $ +*/ + +#include <exception> + + +namespace corsika { + + template <typename TType> + class BitField { + public: + BitField(TType& target); + + class Bit { + public: + Bit(TType& target, TType mask); + + operator bool() const ; + + bool operator~() const ; + + Bit& operator=(const bool value); + + Bit& flip(); + + private: + TType& target_; + TType mask_; + }; + + Bit operator[](unsigned int position); + + Bit at(unsigned int position); + + template <typename TMask> + BitField& mask(const TMask mask, const bool value); + + template <typename TMask> + TType get(const TMask mask); + + private: + TType& target_; + }; + + // helper + template <typename TType> + inline corsika::BitField<TType> asBitField(TType& target) { + return corsika::BitField<TType>(target); + } + +} // namespace corsika + +#include <corsika/detail/framework/utility/BitField.inl> diff --git a/tests/framework/testBitField.cpp b/tests/framework/testBitField.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e568e868be9f541a8d01403f7f4fa9d36e4fcc51 --- /dev/null +++ b/tests/framework/testBitField.cpp @@ -0,0 +1,72 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#include <catch2/catch.hpp> + +#include <corsika/framework/utility/BitField.hpp> + +using namespace corsika; + +TEST_CASE("test of BitField handling") { + + SECTION("BitField based on integer") { + unsigned short test = 0x1337; + auto testBit = BitField(test); + + // 0b1001100110111 + + REQUIRE(testBit[0] == 1); + REQUIRE(testBit[1] == 1); + REQUIRE(testBit[2] == 1); + REQUIRE(testBit[3] == 0); + REQUIRE(testBit[4] == 1); + REQUIRE(testBit[5] == 1); + REQUIRE(testBit[6] == 0); + REQUIRE(testBit[7] == 0); + REQUIRE(testBit[8] == 1); + REQUIRE(testBit[9] == 1); + REQUIRE(testBit[10] == 0); + REQUIRE(testBit[11] == 0); + REQUIRE(testBit[12] == 1); + REQUIRE(testBit[13] == 0); + REQUIRE(testBit[14] == 0); + REQUIRE(testBit[15] == 0); + } + + SECTION("BitField based on struct") { + // This fails to compile, because BitField requires that TType is constructible from int + /* + struct testStruct { + char tmp1[2]; + short tmp2; + } test; + + REQUIRE(sizeof(test) == 4); + auto testBit = BitField(test); + + // 0b1001100110111 + + REQUIRE(testBit[0] == 1); + REQUIRE(testBit[1] == 1); + REQUIRE(testBit[2] == 1); + REQUIRE(testBit[3] == 0); + REQUIRE(testBit[4] == 1); + REQUIRE(testBit[5] == 1); + REQUIRE(testBit[6] == 0); + REQUIRE(testBit[7] == 0); + REQUIRE(testBit[8] == 1); + REQUIRE(testBit[9] == 1); + REQUIRE(testBit[10] == 0); + REQUIRE(testBit[11] == 0); + REQUIRE(testBit[12] == 1); + REQUIRE(testBit[13] == 0); + REQUIRE(testBit[14] == 0); + REQUIRE(testBit[15] == 0); + */ + } +} \ No newline at end of file