32 BufferView(
void* data,
size_t size) : m_Data(
reinterpret_cast<uintptr_t
>(data)), m_Size(size) {
33 assert(data || !size);
36 static BufferView fromAddress(uintptr_t address,
size_t size) {
37 return BufferView(
reinterpret_cast<void*
>(address), size);
40 explicit operator bool()
const {
45 return reinterpret_cast<void*
>(m_Data);
48 uintptr_t address()
const {
60 uint8_t& operator[](
size_t offset)
const {
61 assert(offset < m_Size);
62 return reinterpret_cast<uint8_t*
>(m_Data)[offset];
66 assert(offset <= m_Size);
67 if (offset > m_Size) {
70 return fromAddress(m_Data + offset, m_Size - offset);
74 assert(offset <= m_Size);
75 if (offset > m_Size) {
85 BufferView subview(
size_t offset,
size_t length)
const {
86 assert(offset <= m_Size && length <= (m_Size - offset));
87 if (offset > m_Size || length > (m_Size - offset)) {
90 return fromAddress(m_Data + offset, length);
94 return subview(0, length);
98 T* as(
size_t offset = 0)
const {
99 assert(offset <= m_Size &&
sizeof(T) <= (m_Size - offset));
100 if (offset > m_Size ||
sizeof(T) > (m_Size - offset)) {
103 const uintptr_t address = m_Data + offset;
104 assert((address %
alignof(T)) == 0);
105 if ((address %
alignof(T)) != 0) {
108 return reinterpret_cast<T*
>(address);
126 : m_Storage(storage), m_Capacity(capacity), m_Count(0), m_Size(0) {
127 assert(storage || !capacity);
131 assert(view && !view.empty());
132 if (!view || view.empty() || m_Count >= m_Capacity ||
133 view.size() > (~
static_cast<size_t>(0) - m_Size)) {
137 m_Storage[m_Count++] = view;
138 m_Size += view.size();
151 size_t count()
const {
155 size_t size()
const {
160 assert(index < m_Count);
161 return index < m_Count ? m_Storage[index] :
BufferView();
164 bool copyTo(
void* destination,
size_t length,
size_t offset = 0)
const {
165 assert(destination || !length);
166 assert(offset <= m_Size && length <= (m_Size - offset));
167 if ((!destination && length) || offset > m_Size || length > (m_Size - offset)) {
171 uint8_t* output =
reinterpret_cast<uint8_t*
>(destination);
172 size_t remaining = length;
173 for (
size_t i = 0; i < m_Count && remaining; ++i) {
175 if (offset >= view.size()) {
176 offset -= view.size();
180 const size_t available = view.size() - offset;
181 const size_t chunk = available < remaining ? available : remaining;
182 MemoryCopy(output,
reinterpret_cast<const uint8_t*
>(view.data()) + offset, chunk);
187 return remaining == 0;
190 bool copyFrom(
const void* source,
size_t length,
size_t offset = 0)
const {
191 assert(source || !length);
192 assert(offset <= m_Size && length <= (m_Size - offset));
193 if ((!source && length) || offset > m_Size || length > (m_Size - offset)) {
197 const uint8_t* input =
reinterpret_cast<const uint8_t*
>(source);
198 size_t remaining = length;
199 for (
size_t i = 0; i < m_Count && remaining; ++i) {
201 if (offset >= view.size()) {
202 offset -= view.size();
206 const size_t available = view.size() - offset;
207 const size_t chunk = available < remaining ? available : remaining;
208 MemoryCopy(
reinterpret_cast<uint8_t*
>(view.data()) + offset, input, chunk);
213 return remaining == 0;