kblib 0.2.3
General utilities library for modern C++
bits.cpp
Go to the documentation of this file.
1#define KBLIB_DEF_MACROS 1
2#include "kblib/bits.h"
3#include "catch/catch.hpp"
4#include "kblib/hash.h"
5
6#include <type_traits>
7
8template <typename T>
9struct print;
10
11// These tests are POSIX-based, so spell out that requirement.
12static_assert(CHAR_BIT == 8, "8-bit bytes");
13static_assert(sizeof(short) == 2, "16-bit shorts");
14static_assert(sizeof(int) == 4, "32-bit ints");
15static_assert(sizeof(long) == 8, "64-bit longs");
16
17static_assert(std::is_same<kblib::uint_smallest_t<0>, unsigned char>::value,
18 "uint_smallest_t");
19static_assert(std::is_same<kblib::uint_smallest_t<1>, unsigned char>::value,
20 "uint_smallest_t");
21static_assert(std::is_same<kblib::uint_smallest_t<255>, unsigned char>::value,
22 "uint_smallest_t");
23static_assert(std::is_same<kblib::uint_smallest_t<256>, unsigned short>::value,
24 "uint_smallest_t");
25static_assert(
26 std::is_same<kblib::uint_smallest_t<32768>, unsigned short>::value,
27 "uint_smallest_t");
28static_assert(
29 std::is_same<kblib::uint_smallest_t<65535>, unsigned short>::value,
30 "uint_smallest_t");
31static_assert(std::is_same<kblib::uint_smallest_t<65536>, unsigned int>::value,
32 "uint_smallest_t");
33static_assert(
34 std::is_same<kblib::uint_smallest_t<1u << 31u>, unsigned int>::value,
35 "uint_smallest_t");
36static_assert(
37 std::is_same<kblib::uint_smallest_t<UINT_MAX>, unsigned int>::value,
38 "uint_smallest_t");
39static_assert(
40 std::is_same<kblib::uint_smallest_t<1ul << 32u>, unsigned long>::value,
41 "uint_smallest_t");
42static_assert(
43 std::is_same<kblib::uint_smallest_t<1ul << 63u>, unsigned long>::value,
44 "uint_smallest_t");
45
46// print<kblib::int_smallest_t<1>> t{};
47static_assert(std::is_same<kblib::int_smallest_t<1>, signed char>::value,
48 "int_smallest_t");
49static_assert(std::is_same<kblib::int_smallest_t<127>, signed char>::value,
50 "int_smallest_t");
51static_assert(std::is_same<kblib::int_smallest_t<256>, signed short>::value,
52 "int_smallest_t");
53static_assert(std::is_same<kblib::int_smallest_t<32767>, signed short>::value,
54 "int_smallest_t");
55static_assert(std::is_same<kblib::int_smallest_t<32768>, signed int>::value,
56 "int_smallest_t");
57static_assert(std::is_same<kblib::int_smallest_t<65536>, signed int>::value,
58 "int_smallest_t");
59static_assert(std::is_same<kblib::int_smallest_t<INT_MAX>, signed int>::value,
60 "int_smallest_t");
61static_assert(
62 std::is_same<kblib::int_smallest_t<long(INT_MAX) + 1>, signed long>::value,
63 "int_smallest_t");
64
65#if KBLIB_USE_CXX17
66TEST_CASE("test_trie") {
68 REQUIRE(test.insert({0b1000100010000000, 10}, 1));
69 // has UB, so I hardcoded a test failure as a reminder
70 // std::cout<<test.at({0b1000100010000000, 10})<<'\n';
72 REQUIRE(not +"test.at({0b1000100010000000, 10}) has UB");
73}
74#endif
75
76struct buffer {
77 struct ret_proxy {
78 const char* buf;
79 template <typename T, typename std::enable_if<
81 = 0>
82 operator T() const {
83 T t;
84 std::memcpy(&t, buf, sizeof(T));
85 return t;
86 }
87 };
88 std::vector<char> buf;
89 KBLIB_NODISCARD auto operator[](std::size_t p) -> ret_proxy {
90 return {&buf[p]};
91 }
92};
93
94using kblib::bitfield;
95
96union Addr1 {
98
103
106
108};
109#if __cpp_lib_is_pointer_interconvertible
110static_assert(std::is_pointer_interconvertible_with_class(&Addr1::raw));
111static_assert(
112 std::is_pointer_interconvertible_with_class(&decltype(Addr1::raw)::raw_));
113#endif
114
115TEST_CASE("bitfields1") {
116 static_assert(sizeof(Addr1) == 2, "");
117 Addr1 a;
118 a.l = 0b1100'1100;
119 a.h(0b001'1001);
120 REQUIRE(a.raw == 0b0001'1001'1100'1100);
121 REQUIRE(a.cX() == 0b0'1100);
122 REQUIRE(a.cY == 0b0'1110);
123 REQUIRE(a.nt == 0b10);
124 REQUIRE(a.fY == 0b001);
125}
126
127// Loopy's VRAM address
128struct Addr {
129 std::uint16_t raw{};
130
131 BITFIELD(0u, 5u, cX, raw)
132 BITFIELD(5u, 5u, cY, raw)
133 BITFIELD(10u, 2u, nt, raw)
134 BITFIELD(12u, 3u, fY, raw)
135
136 BITFIELD(0u, 8u, l, raw)
137 BITFIELD(8u, 7u, h, raw)
138
139 BITFIELD(0u, 14u, addr, raw)
140};
141
142KBLIB_NODISCARD constexpr auto test_bitfield() -> Addr {
143 Addr a;
144 a.l() = 0b1100'1100;
145 a.h(0b001'1001);
146 return a;
147}
148
149TEST_CASE("bitfields") {
150 static_assert(sizeof(Addr) == 2, "");
151 constexpr Addr a = test_bitfield();
152 static_assert(a.raw == 0b0001'1001'1100'1100, "");
153 static_assert(a.cX() == 0b0'1100, "");
154 static_assert(a.cY() == 0b0'1110, "");
155 static_assert(a.nt() == 0b10, "");
156 static_assert(a.fY() == 0b001, "");
157
158 static_assert(Addr::get_cX_v<a.raw> == 0b0'1100, "");
159 static_assert(Addr::get_cY_v<a.raw> == 0b0'1110, "");
160 static_assert(Addr::get_nt_v<a.raw> == 0b10, "");
161 static_assert(Addr::get_fY_v<a.raw> == 0b001, "");
162
163 constexpr Addr b = {Addr::set_h_v<0b001'1001, Addr::set_l_v<0b1100'1100>>};
164
165 static_assert(Addr::get_cX_v<b.raw> == 0b0'1100, "");
166 static_assert(Addr::get_cY_v<b.raw> == 0b0'1110, "");
167 static_assert(Addr::get_nt_v<b.raw> == 0b10, "");
168 static_assert(Addr::get_fY_v<b.raw> == 0b001, "");
169}
170
171#if KBLIB_USE_CXX17
172union punner {
173 char storage[sizeof(char*)]{};
176 kblib::union_pun<char16_t[sizeof(char*) / 2], &punner::storage> s;
177};
178
179TEST_CASE("union_punning") {
180 punner pun;
181 std::uintptr_t ival = 0xABCD;
182 kblib::to_bytes_le(ival, pun.storage);
183 REQUIRE(std::equal(std::begin(pun.storage), std::begin(pun.storage) + 4,
184 "\xCD\xAB\0\0"));
185 REQUIRE(pun.val == ival);
186 std::array<char16_t, sizeof(char*) / 2> ustr{u'\xABCD', u'\0'};
187 decltype(ustr) t = pun.s;
188 REQUIRE(t == ustr);
189 REQUIRE(decltype(ustr)(pun.s) == ustr);
190
191 pun.val = 0;
192 const char* c = "";
193 pun.ptr = c;
194 REQUIRE(pun.val == kblib::byte_cast<std::uintptr_t>(c));
195}
196
197TEST_CASE("punning") {
198 kblib::punner<char[], const char*, std::uintptr_t,
199 char16_t[sizeof(char*) / 2]>
200 pun{};
201 void(kblib::get<0>(pun));
202 void(pun.get<1>());
203
204 std::uintptr_t ival = 0xABCD;
205 kblib::to_bytes_le(ival, pun.get<0>());
206 REQUIRE(std::equal(std::begin(pun.get<0>()), std::begin(pun.get<0>()) + 4,
207 "\xCD\xAB\0\0"));
208 REQUIRE(pun.get<2>() == ival);
209 std::array<char16_t, sizeof(char*) / 2> ustr{u'\xABCD', u'\0'};
210 decltype(ustr) t = pun.get<3>();
211 REQUIRE(t == ustr);
212 REQUIRE(decltype(ustr)(pun.get<3>()) == ustr);
213
214 pun.get<2>() = 0;
215 const char* c = "";
216 pun.get<1>() = c;
217 REQUIRE(pun.get<2>() == kblib::byte_cast<std::uintptr_t>(c));
218}
219#endif
KBLIB_NODISCARD constexpr auto test_bitfield() -> Addr
Definition: bits.cpp:142
TEST_CASE("test_trie")
Definition: bits.cpp:66
Provides bit-manipulation functions and classes.
#define BITFIELD(offset, size, name, raw)
Definition: bits.h:861
#define REQUIRE(...)
Definition: catch.hpp:17676
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
constexpr auto test() noexcept -> bool
Definition: main.cpp:68
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4001
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:256
typename int_smallest< I >::type int_smallest_t
Definition: simple.h:202
constexpr auto to_bytes_le(Integral ival, CharT(&dest)[sizeof(Integral)]) noexcept -> void
Definition: hash.h:56
constexpr auto equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) -> bool
Definition: fakestd.h:982
Definition: bits.cpp:128
std::uint16_t raw
Definition: bits.cpp:129
const char * buf
Definition: bits.cpp:78
Definition: bits.cpp:76
KBLIB_NODISCARD auto operator[](std::size_t p) -> ret_proxy
Definition: bits.cpp:89
std::vector< char > buf
Definition: bits.cpp:88
Implements a bitfield abstraction. May be used in a union with other bitfields.
Definition: bits.h:435
Definition: bits.cpp:9
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:146
Definition: bits.cpp:96
bitfield< 12, 3, uint16_t > fY
Definition: bits.cpp:102
bitfield< 0, 16, uint16_t > raw
Definition: bits.cpp:97
bitfield< 0, 5, uint16_t > cX
Definition: bits.cpp:99
bitfield< 5, 5, uint16_t > cY
Definition: bits.cpp:100
bitfield< 0, 14, uint16_t > addr
Definition: bits.cpp:107
bitfield< 10, 2, uint16_t > nt
Definition: bits.cpp:101
bitfield< 8, 7, uint16_t > h
Definition: bits.cpp:105
bitfield< 0, 8, uint16_t > l
Definition: bits.cpp:104
Definition: bits.cpp:172
kblib::union_pun< std::uintptr_t, &punner::storage > val
Definition: bits.cpp:175
kblib::union_pun< char16_t[sizeof(char *)/2], &punner::storage > s
Definition: bits.cpp:176
char storage[sizeof(char *)]
Definition: bits.cpp:173
kblib::union_pun< const char *, &punner::storage > ptr
Definition: bits.cpp:174