The Pedigree Project 0.1
BufferView.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_UTILITIES_BUFFERVIEW_H
21#define KERNEL_UTILITIES_BUFFERVIEW_H
22
23#include "pedigree/kernel/processor/types.h"
24#include "pedigree/kernel/utilities/assert.h"
25#include "pedigree/kernel/utilities/lib.h"
26
29 public:
30 BufferView() : m_Data(0), m_Size(0) {}
31
32 BufferView(void* data, size_t size) : m_Data(reinterpret_cast<uintptr_t>(data)), m_Size(size) {
33 assert(data || !size);
34 }
35
36 static BufferView fromAddress(uintptr_t address, size_t size) {
37 return BufferView(reinterpret_cast<void*>(address), size);
38 }
39
40 explicit operator bool() const {
41 return m_Data != 0;
42 }
43
44 void* data() const {
45 return reinterpret_cast<void*>(m_Data);
46 }
47
48 uintptr_t address() const {
49 return m_Data;
50 }
51
52 size_t size() const {
53 return m_Size;
54 }
55
56 bool empty() const {
57 return m_Size == 0;
58 }
59
60 uint8_t& operator[](size_t offset) const {
61 assert(offset < m_Size);
62 return reinterpret_cast<uint8_t*>(m_Data)[offset];
63 }
64
65 BufferView operator+(size_t offset) const {
66 assert(offset <= m_Size);
67 if (offset > m_Size) {
68 return BufferView();
69 }
70 return fromAddress(m_Data + offset, m_Size - offset);
71 }
72
73 BufferView& operator+=(size_t offset) {
74 assert(offset <= m_Size);
75 if (offset > m_Size) {
76 m_Data = 0;
77 m_Size = 0;
78 return *this;
79 }
80 m_Data += offset;
81 m_Size -= offset;
82 return *this;
83 }
84
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)) {
88 return BufferView();
89 }
90 return fromAddress(m_Data + offset, length);
91 }
92
93 BufferView first(size_t length) const {
94 return subview(0, length);
95 }
96
97 template <typename T>
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)) {
101 return nullptr;
102 }
103 const uintptr_t address = m_Data + offset;
104 assert((address % alignof(T)) == 0);
105 if ((address % alignof(T)) != 0) {
106 return nullptr;
107 }
108 return reinterpret_cast<T*>(address);
109 }
110
111 private:
112 uintptr_t m_Data;
113 size_t m_Size;
114};
115
124 public:
125 BufferViewSequence(BufferView* storage, size_t capacity)
126 : m_Storage(storage), m_Capacity(capacity), m_Count(0), m_Size(0) {
127 assert(storage || !capacity);
128 }
129
130 bool append(const BufferView& view) {
131 assert(view && !view.empty());
132 if (!view || view.empty() || m_Count >= m_Capacity ||
133 view.size() > (~static_cast<size_t>(0) - m_Size)) {
134 return false;
135 }
136
137 m_Storage[m_Count++] = view;
138 m_Size += view.size();
139 return true;
140 }
141
142 void clear() {
143 m_Count = 0;
144 m_Size = 0;
145 }
146
147 bool empty() const {
148 return m_Count == 0;
149 }
150
151 size_t count() const {
152 return m_Count;
153 }
154
155 size_t size() const {
156 return m_Size;
157 }
158
159 BufferView operator[](size_t index) const {
160 assert(index < m_Count);
161 return index < m_Count ? m_Storage[index] : BufferView();
162 }
163
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)) {
168 return false;
169 }
170
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) {
174 const BufferView view = m_Storage[i];
175 if (offset >= view.size()) {
176 offset -= view.size();
177 continue;
178 }
179
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);
183 output += chunk;
184 remaining -= chunk;
185 offset = 0;
186 }
187 return remaining == 0;
188 }
189
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)) {
194 return false;
195 }
196
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) {
200 const BufferView view = m_Storage[i];
201 if (offset >= view.size()) {
202 offset -= view.size();
203 continue;
204 }
205
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);
209 input += chunk;
210 remaining -= chunk;
211 offset = 0;
212 }
213 return remaining == 0;
214 }
215
216 private:
217 BufferView* m_Storage;
218 size_t m_Capacity;
219 size_t m_Count;
220 size_t m_Size;
221};
222
223#endif