Files
fennec/include/fennec/lang/bits.h

225 lines
6.8 KiB
C++

// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file bits.h
/// \brief \ref fennec_lang_bit_manipulation
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_BITS_H
#define FENNEC_LANG_BITS_H
///
/// \page fennec_lang_bit_manipulation Bit Manipulation
///
/// \code #include <fennec/lang/bits.h> \endcode
///
/// This header contains definitions for manipulating the bits of a provided object or pointer.
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_bits">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_cast "ToT bit_cast(const FromT& x)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_cast
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_and "void* bit_and(void* arr, const void* mask, size_t n)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_and
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_and_s "void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_and_s
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_or "void* bit_or(void* arr, const void* mask, size_t n)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_or
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_or_s "void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_or_s
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_xor "void* bit_xor(void* arr, const void* mask, size_t n)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_xor
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::bit_xor_s "void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1)"
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::bit_xor_s
/// </table>
///
///
#include <fennec/lang/intrinsics.h>
#include <fennec/memory/memory.h>
#include <fennec/lang/detail/__bits.h>
namespace fennec
{
///
/// \brief Perform a bitcast of FromT to ToT
///
/// \details Perform a bitcast of FromT to ToT
/// \tparam ToT Type to cast to
/// \tparam FromT Type of the value
/// \param from Value to bit cast
/// \returns A value containing a bitwise copy of the input
template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT))
constexpr ToT bit_cast(const FromT& from)
{
if constexpr(FENNEC_HAS_BUILTIN_BIT_CAST)
return FENNEC_BUILTIN_BIT_CAST(ToT, from);
else
{
ToT to;
fennec::memcpy(&to, &from, sizeof(ToT));
return to;
}
}
///
/// \brief Perform a bit-wise and over an array of bytes
///
/// \details Perform a bitcast of FromT to ToT
/// \param arr the array of bytes to modify
/// \param mask the mask to and against arr
/// \param n the number of bytes
/// \returns the pointer \f$arr\f$
constexpr void* bit_and(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_and(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief Safe version of fennec::bit_and
///
/// \details Safe version of fennec::bit_and
/// \copydetails fennec::bit_and
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_and(arr, mask, n0 < n1 ? n0 : n1); }
///
/// \brief Perform a bit-wise or over an array of bytes
///
/// \details Perform a bit-wise or over an array of bytes
/// \param arr the array of bytes to modify
/// \param mask the mask to or against arr
/// \param n the number of bytes
/// \returns the pointer arr
constexpr void* bit_or(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_or(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief Safe version of fennec::bit_or
///
/// \details Safe version of fennec::bit_or
/// \copydetails fennec::bit_or
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_or(arr, mask, n0 < n1 ? n0 : n1); }
///
/// \brief Perform a bit-wise or over an array of bytes
///
/// \details Perform a bit-wise or over an array of bytes
/// \param arr the array of bytes to modify
/// \param mask the mask to or against arr
/// \param n the number of bytes
/// \returns the pointer arr
constexpr void* bit_xor(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_xor(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief Safe version of fennec::bit_xor
///
/// \details Safe version of fennec::bit_xor
/// \copydetails fennec::bit_xor
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_xor(arr, mask, n0 < n1 ? n0 : n1); }
}
#endif // FENNEC_LANG_BITS_H