|
| 1 | +// |
| 2 | +// This is a derivative work. originally part of the LLVM Project. |
| 3 | +// Licensed under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +// Copyright (c) 2023 Klemens D. Morgenstern |
| 8 | +// |
| 9 | +// |
| 10 | +// Official repository: https://github.com/cppalliance/mrdox |
| 11 | +// |
| 12 | + |
| 13 | +#ifndef MRDOX_METADATA_BITFIELD_HPP |
| 14 | +#define MRDOX_METADATA_BITFIELD_HPP |
| 15 | + |
| 16 | +#include <cstdint> |
| 17 | +#include <limits> |
| 18 | +#include <type_traits> |
| 19 | + |
| 20 | +namespace clang { |
| 21 | +namespace mrdox { |
| 22 | + |
| 23 | + |
| 24 | +constexpr std::uint32_t makeMask(unsigned char Offset, |
| 25 | + unsigned char Size) |
| 26 | +{ |
| 27 | + auto init = std::numeric_limits<std::uint32_t>::max(); |
| 28 | + auto offset = init << Offset; |
| 29 | + auto rest = init >>= (sizeof(std::uint32_t) * 8) - (Offset + Size); |
| 30 | + return offset & rest; |
| 31 | +} |
| 32 | + |
| 33 | + |
| 34 | +template<unsigned char Offset, |
| 35 | + unsigned char Size = 1u, |
| 36 | + typename T = std::uint32_t> |
| 37 | +struct BitField |
| 38 | +{ |
| 39 | + using underlying_type = std::uint32_t; |
| 40 | + underlying_type value; |
| 41 | + |
| 42 | + constexpr static underlying_type mask = makeMask(Offset, Size); |
| 43 | + constexpr static underlying_type offset = Offset; |
| 44 | + constexpr static underlying_type size = Size; |
| 45 | + |
| 46 | + constexpr T get() const noexcept |
| 47 | + { |
| 48 | + constexpr underlying_type simple_mask = makeMask(0u, Offset + Size); |
| 49 | + auto val = value & simple_mask; |
| 50 | + |
| 51 | + if constexpr (std::is_signed<T>::value && (Size + Offset) < (sizeof(underlying_type) * 8u)) |
| 52 | + { |
| 53 | + constexpr underlying_type minus = static_cast<underlying_type>(1) << (Size + Offset); |
| 54 | + if ((val & minus) != static_cast<underlying_type>(0)) |
| 55 | + val |= ~simple_mask; //2s complement - I think |
| 56 | + } |
| 57 | + val >>= Offset; |
| 58 | + return static_cast<T>(val); |
| 59 | + } |
| 60 | + |
| 61 | + constexpr operator T () const noexcept |
| 62 | + { |
| 63 | + return get(); |
| 64 | + } |
| 65 | + |
| 66 | + constexpr void set(T val) noexcept |
| 67 | + { |
| 68 | + auto update = (static_cast<underlying_type>(val) << Offset) & mask; |
| 69 | + value = (value & ~mask) | update; |
| 70 | + } |
| 71 | + |
| 72 | + constexpr T operator=(T val) noexcept { set(val); return val;} |
| 73 | +}; |
| 74 | + |
| 75 | +template<unsigned char Offset> |
| 76 | +using BitFlag = BitField<Offset, 1u, bool>; |
| 77 | + |
| 78 | +using BitFieldFullValue = BitField<0, 32>; |
| 79 | + |
| 80 | +} |
| 81 | +} |
| 82 | + |
| 83 | +#endif //MRDOX_METADATA_BITFIELD_HPP |
0 commit comments