1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ES2PANDA_UTIL_INCLUDE_ENUM_BITOPS_H
17#define ES2PANDA_UTIL_INCLUDE_ENUM_BITOPS_H
18
19#include <type_traits>
20
21// clang-format off
22#define ENUMBITOPS_OPERATORS \
23    enumbitops::operator~,   \
24    enumbitops::operator!,   \
25    enumbitops::operator|,   \
26    enumbitops::operator&,   \
27    enumbitops::operator^,   \
28    enumbitops::operator|=,  \
29    enumbitops::operator&=,  \
30    enumbitops::operator^=
31// clang-format on
32
33namespace enumbitops {
34
35template <class T>
36struct IsAllowedType : std::false_type {
37};
38
39template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
40inline constexpr T operator~(T a)
41{
42    using Utype = std::underlying_type_t<T>;
43    // NOLINTNEXTLINE(hicpp-signed-bitwise)
44    return static_cast<T>(~static_cast<Utype>(a));
45}
46
47template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
48inline constexpr bool operator!(T a)
49{
50    using Utype = std::underlying_type_t<T>;
51    // NOLINTNEXTLINE(hicpp-signed-bitwise)
52    return (!static_cast<Utype>(a));
53}
54
55template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
56inline constexpr T operator|(T a, T b)
57{
58    using Utype = std::underlying_type_t<T>;
59    // NOLINTNEXTLINE(hicpp-signed-bitwise)
60    return static_cast<T>(static_cast<Utype>(a) | static_cast<Utype>(b));
61}
62
63template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
64inline constexpr std::underlying_type_t<T> operator&(T a, T b)
65{
66    using Utype = std::underlying_type_t<T>;
67    // NOLINTNEXTLINE(hicpp-signed-bitwise)
68    return static_cast<Utype>(static_cast<Utype>(a) & static_cast<Utype>(b));
69}
70
71template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
72inline constexpr T operator^(T a, T b)
73{
74    using Utype = std::underlying_type_t<T>;
75    // NOLINTNEXTLINE(hicpp-signed-bitwise)
76    return static_cast<T>(static_cast<Utype>(a) ^ static_cast<Utype>(b));
77}
78
79template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
80inline constexpr T &operator|=(T &a, T b)
81{
82    // NOLINTNEXTLINE(hicpp-signed-bitwise)
83    return a = a | b;
84}
85
86template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
87inline constexpr T &operator&=(T &a, T b)
88{
89    using Utype = std::underlying_type_t<T>;
90    // NOLINTNEXTLINE(hicpp-signed-bitwise)
91    return a = static_cast<T>(static_cast<Utype>(a) & static_cast<Utype>(b));
92}
93
94template <class T, std::enable_if_t<IsAllowedType<T>::value, bool> = true>
95inline constexpr T &operator^=(T &a, T b)
96{
97    // NOLINTNEXTLINE(hicpp-signed-bitwise)
98    return a = a ^ b;
99}
100
101}  // namespace enumbitops
102
103#endif
104