File: byte.h

package info (click to toggle)
dolphin-emu 2512%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 76,328 kB
  • sloc: cpp: 499,023; ansic: 119,674; python: 6,547; sh: 2,338; makefile: 1,093; asm: 726; pascal: 257; javascript: 183; perl: 97; objc: 75; xml: 30
file content (178 lines) | stat: -rw-r--r-- 5,370 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
 * \file libipc/byte.h
 * \author mutouyun (orz@orzz.org)
 * \brief Define the byte type.
 */
#pragma once

#include <type_traits>
#include <cstdint>
#include <cstddef>  // std::byte (since C++17)

#include "libipc/imp/detect_plat.h"
#include "libipc/imp/span.h"
#include "libipc/imp/fmt.h"

#if defined(LIBIPC_CPP_17) && defined(__cpp_lib_byte)
#define LIBIPC_CPP_LIB_BYTE_
#endif // __cpp_lib_byte

namespace ipc {

class byte;

namespace detail_byte {

template <typename T>
using is_integral = 
  typename std::enable_if<std::is_integral<T>::value>::type;

template <typename T>
using is_not_byte = 
  typename std::enable_if<!std::is_same<
  typename std::remove_cv<T>::type, byte>::value>::type;

} // namespace detail_byte

/**
 * \brief A distinct type that implements the concept of byte as specified in the C++ language definition.
 * \see https://en.cppreference.com/w/cpp/types/byte
 */
class byte {
  std::uint8_t bits_;

public:
  byte() noexcept = default;

  template <typename T, typename = detail_byte::is_integral<T>>
  constexpr byte(T v) noexcept
    : bits_(static_cast<std::uint8_t>(v)) {}

#ifdef LIBIPC_CPP_LIB_BYTE_
  constexpr byte(std::byte b) noexcept
    : byte(std::to_integer<std::uint8_t>(b)) {}
#endif // LIBIPC_CPP_LIB_BYTE_

  template <typename T, typename = detail_byte::is_integral<T>>
  constexpr operator T() const noexcept {
    return static_cast<T>(bits_);
  }

#ifdef LIBIPC_CPP_LIB_BYTE_
  constexpr operator std::byte() const noexcept {
    /// \brief C++17 relaxed enum class initialization rules.
    /// \see https://en.cppreference.com/w/cpp/language/enum#enum_relaxed_init_cpp17
    return std::byte{bits_};
  }
#endif // LIBIPC_CPP_LIB_BYTE_

  friend bool operator==(byte const &lhs, byte const &rhs) noexcept {
    return lhs.bits_ == rhs.bits_;
  }

  friend bool operator!=(byte const &lhs, byte const &rhs) noexcept {
    return !(lhs == rhs);
  }
};

/**
 * \brief Non-member functions.
 */

template <typename T, typename = detail_byte::is_integral<T>>
constexpr T to_integer(byte b) noexcept {
  return T(b);
}

/// \brief std::operator<<, operator>>

template <typename T, typename = detail_byte::is_integral<T>>
constexpr byte operator<<(byte b, T shift) noexcept {
  return byte(to_integer<unsigned>(b) << shift);
}

template <typename T, typename = detail_byte::is_integral<T>>
constexpr byte operator>>(byte b, T shift) noexcept {
  return byte(to_integer<unsigned>(b) >> shift);
}

/// \brief std::operator<<=, operator>>=

template <typename T, typename = detail_byte::is_integral<T>>
constexpr byte &operator<<=(byte &b, T shift) noexcept {
  return b = b << shift;
}

template <typename T, typename = detail_byte::is_integral<T>>
constexpr byte &operator>>=(byte &b, T shift) noexcept {
  return b = b >> shift;
}

/// \brief std::operator|, operator&, operator^, operator~

constexpr byte operator|(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) | to_integer<unsigned>(r)); }
constexpr byte operator&(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) & to_integer<unsigned>(r)); }
constexpr byte operator^(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) ^ to_integer<unsigned>(r)); }
constexpr byte operator~(byte b)         noexcept { return byte(~to_integer<unsigned>(b)); }

/// \brief std::operator|=, operator&=, operator^=

constexpr byte &operator|=(byte &l, byte r) noexcept { return l = l | r; }
constexpr byte &operator&=(byte &l, byte r) noexcept { return l = l & r; }
constexpr byte &operator^=(byte &l, byte r) noexcept { return l = l ^ r; }

/// \brief Cast pointer to byte*.

template <typename T, typename = detail_byte::is_not_byte<T>>
byte *byte_cast(T *p) noexcept {
  return reinterpret_cast<byte *>(p);
}

template <typename T, typename = detail_byte::is_not_byte<T>>
byte const *byte_cast(T const *p) noexcept {
  return reinterpret_cast<byte const *>(p);
}

/// \brief Cast byte* to a pointer of another type.

template <typename T, typename = detail_byte::is_not_byte<T>>
T *byte_cast(byte *p) noexcept {
  if (reinterpret_cast<std::size_t>(p) % alignof(T) != 0) {
    return nullptr;
  }
  return reinterpret_cast<T *>(p);
}

template <typename T, typename U = typename std::add_const<T>::type, 
          typename = detail_byte::is_not_byte<T>>
U *byte_cast(byte const *p) noexcept {
  if (reinterpret_cast<std::size_t>(p) % alignof(T) != 0) {
    return nullptr;
  }
  return reinterpret_cast<U *>(p);
}

/// \brief Converts a span into a view of its underlying bytes.
/// \see https://en.cppreference.com/w/cpp/container/span/as_bytes

template <typename T, 
          typename Byte = typename std::conditional<std::is_const<T>::value, byte const, byte>::type>
auto as_bytes(span<T> s) noexcept -> span<Byte> {
  return {byte_cast(s.data()), s.size_bytes()};
}

/// \brief Custom defined fmt_to method for imp::fmt
namespace detail_tag_invoke {

inline bool tag_invoke(decltype(ipc::fmt_to), fmt_context &ctx, ipc::byte b) {
  return ipc::to_string(ctx, static_cast<std::uint8_t>(b), "02x");
}

template <typename T, 
          typename = std::enable_if_t<std::is_same<std::decay_t<T>, ipc::byte>::value>>
bool tag_invoke(decltype(ipc::fmt_to), fmt_context &ctx, fmt_ref<T> arg) noexcept {
  return ipc::to_string(ctx, static_cast<std::uint8_t>(arg.param), arg.fstr);
}

} // namespace detail_tag_invoke
} // namespace ipc