blob: cdab861796d1b999eaf2b1b946539639e4400d08 (
plain) (
blame)
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
|
/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */
#ifndef MPT_ENDIAN_INT24_HPP
#define MPT_ENDIAN_INT24_HPP
#include "mpt/base/bit.hpp"
#include "mpt/base/macros.hpp"
#include "mpt/base/memory.hpp"
#include "mpt/base/namespace.hpp"
#include <array>
#include <limits>
#include <type_traits>
#include <cstddef>
namespace mpt {
inline namespace MPT_INLINE_NS {
struct uint24 {
std::array<std::byte, 3> bytes;
uint24() = default;
template <typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
explicit uint24(T other) noexcept {
using Tunsigned = typename std::make_unsigned<T>::type;
MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) {
bytes[0] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 16) & 0xff));
bytes[1] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 8) & 0xff));
bytes[2] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 0) & 0xff));
} else {
bytes[0] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 0) & 0xff));
bytes[1] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 8) & 0xff));
bytes[2] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 16) & 0xff));
}
}
operator int() const noexcept {
MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) {
return (mpt::byte_cast<uint8>(bytes[0]) * 65536) + (mpt::byte_cast<uint8>(bytes[1]) * 256) + mpt::byte_cast<uint8>(bytes[2]);
} else {
return (mpt::byte_cast<uint8>(bytes[2]) * 65536) + (mpt::byte_cast<uint8>(bytes[1]) * 256) + mpt::byte_cast<uint8>(bytes[0]);
}
}
};
static_assert(sizeof(uint24) == 3);
struct int24 {
std::array<std::byte, 3> bytes;
int24() = default;
template <typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
explicit int24(T other) noexcept {
using Tunsigned = typename std::make_unsigned<T>::type;
MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) {
bytes[0] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 16) & 0xff));
bytes[1] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 8) & 0xff));
bytes[2] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 0) & 0xff));
} else {
bytes[0] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 0) & 0xff));
bytes[1] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 8) & 0xff));
bytes[2] = mpt::byte_cast<std::byte>(static_cast<uint8>((static_cast<Tunsigned>(other) >> 16) & 0xff));
}
}
operator int() const noexcept {
MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) {
return (static_cast<int8>(mpt::byte_cast<uint8>(bytes[0])) * 65536) + (mpt::byte_cast<uint8>(bytes[1]) * 256) + mpt::byte_cast<uint8>(bytes[2]);
} else {
return (static_cast<int8>(mpt::byte_cast<uint8>(bytes[2])) * 65536) + (mpt::byte_cast<uint8>(bytes[1]) * 256) + mpt::byte_cast<uint8>(bytes[0]);
}
}
};
static_assert(sizeof(int24) == 3);
} // namespace MPT_INLINE_NS
} // namespace mpt
#if !defined(CPPCHECK)
// work-around crash in cppcheck 2.4.1
namespace std {
template <>
class numeric_limits<mpt::uint24> : public std::numeric_limits<mpt::uint32> {
public:
static constexpr mpt::uint32 min() noexcept {
return 0;
}
static constexpr mpt::uint32 lowest() noexcept {
return 0;
}
static constexpr mpt::uint32 max() noexcept {
return 0x00ffffff;
}
};
template <>
class numeric_limits<mpt::int24> : public std::numeric_limits<mpt::int32> {
public:
static constexpr mpt::int32 min() noexcept {
return 0 - 0x00800000;
}
static constexpr mpt::int32 lowest() noexcept {
return 0 - 0x00800000;
}
static constexpr mpt::int32 max() noexcept {
return 0 + 0x007fffff;
}
};
} // namespace std
#endif // !CPPCHECK
#endif // MPT_ENDIAN_INT24_HPP
|