Everett
Loading...
Searching...
No Matches
word_view.h
Go to the documentation of this file.
1
13#pragma once
14
16
17#include <bit>
18#include <cstddef>
19#include <cstdint>
20#include <cstring>
21#include <span>
22#include <stdexcept>
23#include <type_traits>
24
25namespace everett {
26 struct sample_view;
27
28 // Borrows native words or portable little-endian bytes. Construction reads
29 // no elements; loads use memcpy and need neither aligned addresses nor live
30 // uint64_t objects in the backing mapping. The owner must outlive this view.
31 struct word_view {
32 word_view() = default;
33 explicit word_view(std::span<std::uint64_t const> words) noexcept
34 : bytes_(std::as_bytes(words)), little_(std::endian::native == std::endian::little) {}
35
36 static word_view little_endian(std::span<std::byte const> bytes) {
37 if (bytes.size() & 7) error_detail::raise<std::invalid_argument>("word section length is not a multiple of eight");
38 return {bytes, true};
39 }
40
41 std::size_t size() const noexcept { return bytes_.size() >> 3; }
42 bool empty() const noexcept { return bytes_.empty(); }
43 std::span<std::byte const> bytes() const noexcept { return bytes_; }
44 bool is_little_endian() const noexcept { return little_; }
45 word_view subspan(std::size_t offset, std::size_t count = std::dynamic_extent) const {
46 if (offset > size()) error_detail::raise<std::out_of_range>("word section offset");
47 if (count == std::dynamic_extent) count = size() - offset;
48 if (count > size() - offset) error_detail::raise<std::out_of_range>("word section length");
49 return {bytes_.subspan(offset << 3, count << 3), little_};
50 }
51
52 std::uint64_t operator[](std::size_t index) const {
53 if (index >= size()) error_detail::raise<std::out_of_range>("word section index");
54 std::uint64_t value;
55 std::memcpy(&value, bytes_.data() + (index << 3), 8);
56 if constexpr (std::endian::native == std::endian::big) {
57 if (little_) {
58 value = ((value & 0x00ff00ff00ff00ffull) << 8) | ((value >> 8) & 0x00ff00ff00ff00ffull);
59 value = ((value & 0x0000ffff0000ffffull) << 16) | ((value >> 16) & 0x0000ffff0000ffffull);
60 value = (value << 32) | (value >> 32);
61 }
62 }
63 return value;
64 }
65
66 private:
67 friend struct sample_view;
68 static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big,
69 "directory words require a byte-ordered host");
70 word_view(std::span<std::byte const> bytes, bool little) noexcept : bytes_(bytes), little_(little) {}
71 std::span<std::byte const> bytes_;
72 bool little_ = true;
73 };
74
75 struct sample_value {
76 std::uint64_t first;
77 std::uint64_t sparse;
78 };
79
80 // Select samples are explicit pairs of words. Existing native sample structs
81 // keep their public names; their layout is checked before borrowing bytes.
82 struct sample_view {
83 sample_view() = default;
84 template <class Sample> explicit sample_view(std::span<Sample const> samples) noexcept
85 : words_(std::as_bytes(samples), std::endian::native == std::endian::little) {
86 static_assert(std::is_standard_layout_v<Sample> && std::is_trivially_copyable_v<Sample>);
87 static_assert(std::is_same_v<decltype(Sample::first), std::uint64_t> &&
88 std::is_same_v<decltype(Sample::sparse), std::uint64_t>);
89 static_assert(sizeof(Sample) == 16 && offsetof(Sample, first) == 0 && offsetof(Sample, sparse) == 8);
90 }
91
92 static sample_view little_endian(std::span<std::byte const> bytes) {
93 if (bytes.size() & 15) error_detail::raise<std::invalid_argument>("sample section length is not a multiple of sixteen");
95 }
96
97 std::size_t size() const noexcept { return words_.size() >> 1; }
98 bool empty() const noexcept { return !size(); }
99 word_view words() const noexcept { return words_; }
100 std::span<std::byte const> bytes() const noexcept { return words_.bytes(); }
101 sample_value operator[](std::size_t index) const {
102 if (index >= size()) error_detail::raise<std::out_of_range>("sample section index");
103 return {words_[index << 1], words_[(index << 1) + 1]};
104 }
105
106 private:
107 explicit sample_view(word_view words) noexcept : words_(words) {}
109 };
110}
Outlines exceptional check failures while preserving their types and messages.
Definition active_engine.h:18
Definition word_view.h:75
std::uint64_t sparse
Definition word_view.h:77
std::uint64_t first
Definition word_view.h:76
Definition word_view.h:82
std::span< std::byte const > bytes() const noexcept
Definition word_view.h:100
sample_view(std::span< Sample const > samples) noexcept
Definition word_view.h:84
std::size_t size() const noexcept
Definition word_view.h:97
sample_view(word_view words) noexcept
Definition word_view.h:107
word_view words_
Definition word_view.h:108
bool empty() const noexcept
Definition word_view.h:98
static sample_view little_endian(std::span< std::byte const > bytes)
Definition word_view.h:92
sample_value operator[](std::size_t index) const
Definition word_view.h:101
word_view words() const noexcept
Definition word_view.h:99
Definition word_view.h:31
word_view subspan(std::size_t offset, std::size_t count=std::dynamic_extent) const
Definition word_view.h:45
bool empty() const noexcept
Definition word_view.h:42
static word_view little_endian(std::span< std::byte const > bytes)
Definition word_view.h:36
std::size_t size() const noexcept
Definition word_view.h:41
word_view(std::span< std::uint64_t const > words) noexcept
Definition word_view.h:33
word_view(std::span< std::byte const > bytes, bool little) noexcept
Definition word_view.h:70
std::uint64_t operator[](std::size_t index) const
Definition word_view.h:52
std::span< std::byte const > bytes() const noexcept
Definition word_view.h:43
bool is_little_endian() const noexcept
Definition word_view.h:44
bool little_
Definition word_view.h:72
std::span< std::byte const > bytes_
Definition word_view.h:71