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.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';
71 REQUIRE(not +"test.at({0b1000100010000000, 10}) has UB");
72}
73#endif
74
75struct buffer {
76 struct ret_proxy {
77 const char* buf;
78 template <typename T, typename std::enable_if<
79 std::is_trivially_copyable<T>::value, int>::type
80 = 0>
81 operator T() const {
82 T t;
83 std::memcpy(&t, buf, sizeof(T));
84 return t;
85 }
86 };
87 std::vector<char> buf;
88 KBLIB_NODISCARD auto operator[](std::size_t p) -> ret_proxy {
89 return {&buf[p]};
90 }
91};
92
93using kblib::bitfield;
94
95union Addr1 {
97
102
105
107};
108#if __cpp_lib_is_pointer_interconvertible
109static_assert(std::is_pointer_interconvertible_with_class(&Addr1::raw));
110static_assert(
111 std::is_pointer_interconvertible_with_class(&decltype(Addr1::raw)::raw_));
112#endif
113
114TEST_CASE("bitfields1") {
115 static_assert(sizeof(Addr1) == 2, "");
116 Addr1 a;
117 a.l = 0b1100'1100;
118 a.h(0b001'1001);
119 REQUIRE(a.raw == 0b0001'1001'1100'1100);
120 REQUIRE(a.cX() == 0b0'1100);
121 REQUIRE(a.cY == 0b0'1110);
122 REQUIRE(a.nt == 0b10);
123 REQUIRE(a.fY == 0b001);
124}
125
126// Loopy's VRAM address
127struct Addr {
128 std::uint16_t raw{};
129
130 BITFIELD(0u, 5u, cX, raw)
131 BITFIELD(5u, 5u, cY, raw)
132 BITFIELD(10u, 2u, nt, raw)
133 BITFIELD(12u, 3u, fY, raw)
134
135 BITFIELD(0u, 8u, l, raw)
136 BITFIELD(8u, 7u, h, raw)
137
138 BITFIELD(0u, 14u, addr, raw)
139};
140
141KBLIB_NODISCARD constexpr auto test_bitfield() -> Addr {
142 Addr a;
143 a.l() = 0b1100'1100;
144 a.h(0b001'1001);
145 return a;
146}
147
148TEST_CASE("bitfields") {
149 static_assert(sizeof(Addr) == 2, "");
150 constexpr Addr a = test_bitfield();
151 static_assert(a.raw == 0b0001'1001'1100'1100, "");
152 static_assert(a.cX() == 0b0'1100, "");
153 static_assert(a.cY() == 0b0'1110, "");
154 static_assert(a.nt() == 0b10, "");
155 static_assert(a.fY() == 0b001, "");
156
157 static_assert(Addr::get_cX_v<a.raw> == 0b0'1100, "");
158 static_assert(Addr::get_cY_v<a.raw> == 0b0'1110, "");
159 static_assert(Addr::get_nt_v<a.raw> == 0b10, "");
160 static_assert(Addr::get_fY_v<a.raw> == 0b001, "");
161
162 constexpr Addr b = {Addr::set_h_v<0b001'1001, Addr::set_l_v<0b1100'1100>>};
163
164 static_assert(Addr::get_cX_v<b.raw> == 0b0'1100, "");
165 static_assert(Addr::get_cY_v<b.raw> == 0b0'1110, "");
166 static_assert(Addr::get_nt_v<b.raw> == 0b10, "");
167 static_assert(Addr::get_fY_v<b.raw> == 0b001, "");
168}
169
170#if KBLIB_USE_CXX17
171union punner {
172 char storage[sizeof(char*)]{};
175 kblib::union_pun<char16_t[sizeof(char*) / 2], &punner::storage> s;
176};
177
178TEST_CASE("union_punning") {
179 punner pun;
180 std::uintptr_t ival = 0xABCD;
181 kblib::to_bytes_le(ival, pun.storage);
182 REQUIRE(std::equal(std::begin(pun.storage), std::begin(pun.storage) + 4,
183 "\xCD\xAB\0\0"));
184 REQUIRE(pun.val == ival);
185 std::array<char16_t, sizeof(char*) / 2> ustr{u'\xABCD', u'\0'};
186 decltype(ustr) t = pun.s;
187 REQUIRE(t == ustr);
188 REQUIRE(decltype(ustr)(pun.s) == ustr);
189
190 pun.val = 0;
191 const char* c = "";
192 pun.ptr = c;
193 REQUIRE(pun.val == kblib::byte_cast<std::uintptr_t>(c));
194}
195
196TEST_CASE("punning") {
197 kblib::punner<char[], const char*, std::uintptr_t,
198 char16_t[sizeof(char*) / 2]>
199 pun{};
200 void(kblib::get<0>(pun));
201 void(pun.get<1>());
202
203 std::uintptr_t ival = 0xABCD;
204 kblib::to_bytes_le(ival, pun.get<0>());
205 REQUIRE(std::equal(std::begin(pun.get<0>()), std::begin(pun.get<0>()) + 4,
206 "\xCD\xAB\0\0"));
207 REQUIRE(pun.get<2>() == ival);
208 std::array<char16_t, sizeof(char*) / 2> ustr{u'\xABCD', u'\0'};
209 decltype(ustr) t = pun.get<3>();
210 REQUIRE(t == ustr);
211 REQUIRE(decltype(ustr)(pun.get<3>()) == ustr);
212
213 pun.get<2>() = 0;
214 const char* c = "";
215 pun.get<1>() = c;
216 REQUIRE(pun.get<2>() == kblib::byte_cast<std::uintptr_t>(c));
217}
218#endif
KBLIB_NODISCARD constexpr auto test_bitfield() -> Addr
Definition: bits.cpp:141
TEST_CASE("test_trie")
Definition: bits.cpp:66
Provides bit-manipulation functions and classes.
#define BITFIELD(offset, size, name, raw)
Definition: bits.h:863
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
constexpr auto test() noexcept -> bool
Definition: main.cpp:68
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
typename int_smallest< I >::type int_smallest_t
Definition: simple.h:201
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:966
Definition: bits.cpp:127
std::uint16_t raw
Definition: bits.cpp:128
const char * buf
Definition: bits.cpp:77
Definition: bits.cpp:75
KBLIB_NODISCARD auto operator[](std::size_t p) -> ret_proxy
Definition: bits.cpp:88
std::vector< char > buf
Definition: bits.cpp:87
Implements a bitfield abstraction. May be used in a union with other bitfields.
Definition: bits.h:437
Definition: bits.cpp:9
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129
Definition: bits.cpp:95
bitfield< 12, 3, uint16_t > fY
Definition: bits.cpp:101
bitfield< 0, 16, uint16_t > raw
Definition: bits.cpp:96
bitfield< 0, 5, uint16_t > cX
Definition: bits.cpp:98
bitfield< 5, 5, uint16_t > cY
Definition: bits.cpp:99
bitfield< 0, 14, uint16_t > addr
Definition: bits.cpp:106
bitfield< 10, 2, uint16_t > nt
Definition: bits.cpp:100
bitfield< 8, 7, uint16_t > h
Definition: bits.cpp:104
bitfield< 0, 8, uint16_t > l
Definition: bits.cpp:103
Definition: bits.cpp:171
kblib::union_pun< std::uintptr_t, &punner::storage > val
Definition: bits.cpp:174
kblib::union_pun< char16_t[sizeof(char *)/2], &punner::storage > s
Definition: bits.cpp:175
char storage[sizeof(char *)]
Definition: bits.cpp:172
kblib::union_pun< const char *, &punner::storage > ptr
Definition: bits.cpp:173