roo_io
API Documentation for roo_io
Loading...
Searching...
No Matches
fill.h
Go to the documentation of this file.
1#pragma once
2
3// Utility methods for fast-filling memory with specified bit patterns. The
4// methods optimize performance by reducing the frequency of branching and
5// writing large data blocks when possible.
6
7#include <inttypes.h>
8
9#include <cstring>
10
11#include "roo_io/base/byte.h"
12
13namespace roo_io {
14
15template <int bytes>
16inline void PatternWrite(byte* buf, const byte* val);
17
18template <>
19inline void PatternWrite<1>(byte* buf, const byte* val) {
20 *buf = *val;
21}
22
23template <>
24inline void PatternWrite<2>(byte* buf, const byte* val) {
25 *((uint16_t*)buf) = *((const uint16_t*)val);
26}
27
28template <>
29inline void PatternWrite<3>(byte* buf, const byte* val) {
30 buf[0] = val[0];
31 buf[1] = val[1];
32 buf[2] = val[2];
33}
34
35template <>
36inline void PatternWrite<4>(byte* buf, const byte* val) {
37 *((uint32_t*)buf) = *((const uint32_t*)val);
38}
39
40template <int bytes>
41inline void PatternFill(byte* buf, size_t count, const byte* val);
42
43template <>
44inline void PatternFill<1>(byte* buf, size_t count, const byte* val) {
45 memset(buf, (int)*val, count);
46}
47
48namespace internal {
49
51 while (count >= 8) {
52 buf[0] = val;
53 buf[1] = val;
54 buf[2] = val;
55 buf[3] = val;
56 buf[4] = val;
57 buf[5] = val;
58 buf[6] = val;
59 buf[7] = val;
60 buf += 8;
61 count -= 8;
62 }
63 if (count == 0) return;
64 *buf++ = val;
65 --count;
66 if (count == 0) return;
67 *buf++ = val;
68 --count;
69 if (count == 0) return;
70 *buf++ = val;
71 --count;
72 if (count == 0) return;
73 *buf++ = val;
74 --count;
75 if (count == 0) return;
76 *buf++ = val;
77 --count;
78 if (count == 0) return;
79 *buf++ = val;
80 --count;
81 if (count == 0) return;
82 *buf = val;
83 return;
84}
85
87 if (((intptr_t)buf & 3) != 0) {
88 *buf++ = val;
89 --count;
90 }
91 uint32_t val32 = (uint32_t)val << 16 | val;
93 if ((count % 2) != 0) {
94 buf[count - 1] = val;
95 }
96}
97
98} // namespace internal
99
100template <>
101inline void PatternFill<2>(byte* buf, size_t count, const byte* val) {
102 if (count < 8) {
103 if (count == 0) return;
104 *buf++ = val[0];
105 *buf++ = val[1];
106 --count;
107 if (count == 0) return;
108 *buf++ = val[0];
109 *buf++ = val[1];
110 --count;
111 if (count == 0) return;
112 *buf++ = val[0];
113 *buf++ = val[1];
114 --count;
115 if (count == 0) return;
116 *buf++ = val[0];
117 *buf++ = val[1];
118 --count;
119 if (count == 0) return;
120 *buf++ = val[0];
121 *buf++ = val[1];
122 --count;
123 if (count == 0) return;
124 *buf++ = val[0];
125 *buf++ = val[1];
126 --count;
127 if (count == 0) return;
128 *buf++ = val[0];
129 *buf++ = val[1];
130 --count;
131 return;
132 }
133 if (val[0] == val[1]) {
134 memset(buf, (int)val[0], count * 2);
135 return;
136 }
137 if ((((intptr_t)buf) & 1) != 0) {
138 // Mis-aligned.
139 *buf++ = val[0];
141 ((byte*)&aligned)[0] = val[1];
142 ((byte*)&aligned)[1] = val[0];
144 buf[(count - 1) * 2] = val[1];
145 return;
146 } else {
148 }
149}
150
151template <>
152inline void PatternFill<3>(byte* buf, size_t count, const byte* val) {
153 // Get to the point where we're aligned on 4 bytes.
154 if (count < 8) {
155 if (count == 0) return;
156 *buf++ = val[0];
157 *buf++ = val[1];
158 *buf++ = val[2];
159 --count;
160 if (count == 0) return;
161 *buf++ = val[0];
162 *buf++ = val[1];
163 *buf++ = val[2];
164 --count;
165 if (count == 0) return;
166 *buf++ = val[0];
167 *buf++ = val[1];
168 *buf++ = val[2];
169 --count;
170 if (count == 0) return;
171 *buf++ = val[0];
172 *buf++ = val[1];
173 *buf++ = val[2];
174 --count;
175 if (count == 0) return;
176 *buf++ = val[0];
177 *buf++ = val[1];
178 *buf++ = val[2];
179 --count;
180 if (count == 0) return;
181 *buf++ = val[0];
182 *buf++ = val[1];
183 *buf++ = val[2];
184 --count;
185 if (count == 0) return;
186 *buf++ = val[0];
187 *buf++ = val[1];
188 *buf++ = val[2];
189 --count;
190 return;
191 }
192
193 if (((intptr_t)buf & 3) != 0) {
194 *buf++ = val[0];
195 *buf++ = val[1];
196 *buf++ = val[2];
197 --count;
198 if (((intptr_t)buf & 3) != 0) {
199 *buf++ = val[0];
200 *buf++ = val[1];
201 *buf++ = val[2];
202 --count;
203 if (((intptr_t)buf & 3) != 0) {
204 *buf++ = val[0];
205 *buf++ = val[1];
206 *buf++ = val[2];
207 --count;
208 }
209 }
210 }
211
212 byte block[] = {val[0], val[1], val[2], val[0], val[1], val[2],
213 val[0], val[1], val[2], val[0], val[1], val[2]};
214 const uint32_t* block32 = (const uint32_t*)block;
216 while (count > 8) {
217 *buf32++ = block32[0];
218 *buf32++ = block32[1];
219 *buf32++ = block32[2];
220 *buf32++ = block32[0];
221 *buf32++ = block32[1];
222 *buf32++ = block32[2];
223 count -= 8;
224 }
225 if (count > 4) {
226 *buf32++ = block32[0];
227 *buf32++ = block32[1];
228 *buf32++ = block32[2];
229 count -= 4;
230 }
231 buf = (byte*)buf32;
232 while (count-- > 0) {
233 *buf++ = val[0];
234 *buf++ = val[1];
235 *buf++ = val[2];
236 }
237}
238
239template <>
240inline void PatternFill<4>(byte* buf, size_t count, const byte* val) {
241 if ((val[0] == val[1]) && (val[0] == val[2]) && (val[0] == val[3])) {
242 memset(buf, (int)val[0], count * 4);
243 return;
244 }
245 if (count == 0) return;
246 int offset = ((intptr_t)buf) & 3;
247 if (offset != 0) {
248 // Mis-aligned.
249 memcpy(buf, val, 4 - offset);
251 ((byte*)&aligned)[0] = val[4 - offset];
252 ((byte*)&aligned)[1] = val[(5 - offset) & 3];
253 ((byte*)&aligned)[2] = val[(6 - offset) & 3];
254 ((byte*)&aligned)[3] = val[(7 - offset) & 3];
256 aligned);
257 memcpy(buf + count * 4 - offset, val + 4 - offset, offset);
258 } else {
260 *(const uint32_t*)val);
261 }
262}
263
264// Fills 'count' consecutive bits of memory (in MSB order), starting at the
265// given bit offset of the given buffer.
266inline void BitFill(byte* buf, uint32_t offset, size_t count, bool value) {
267 buf += (offset / 8);
268 offset %= 8;
269 if (value) {
270 if (offset > 0) {
271 if (offset + count < 8) {
272 *buf |= (byte)(((1 << count) - 1) << offset);
273 return;
274 }
275 *buf++ |= (byte)(0xFF << offset);
276 count -= (8 - offset);
277 offset = 0;
278 }
279 memset(buf, 0xFF, count / 8);
280 buf += (count / 8);
281 count %= 8;
282 if (count == 0) return;
283 *buf |= (byte)((1 << count) - 1);
284 } else {
285 if (offset > 0) {
286 if (offset + count < 8) {
287 *buf &= (byte)(~(((1 << count) - 1) << offset));
288 return;
289 }
290 *buf++ &= (byte)(~(0xFF << offset));
291 count -= (8 - offset);
292 offset = 0;
293 }
294 memset(buf, 0x00, count / 8);
295 buf += (count / 8);
296 count %= 8;
297 if (count == 0) return;
298 *buf &= (byte)(~((1 << count) - 1));
299 }
300}
301
302inline void NibbleFill(byte* buf, uint32_t offset, size_t count, byte value) {
303 if ((offset % 2) == 1) {
304 byte& first = buf[offset / 2];
305 first &= byte{0xF0};
306 first |= value;
307 offset++;
308 --count;
309 if (count == 0) return;
310 }
311 if (count >= 2) {
312 memset(buf + offset / 2, (int)(value | (value << 4)), count / 2);
313 offset += count;
314 count %= 2;
315 }
316 if (count > 0) {
317 byte& last = buf[offset / 2];
318 last &= byte{0x0F};
319 last |= (value << 4);
320 }
321}
322
323} // namespace roo_io
void pattern_fill_32_aligned(uint32_t *buf, size_t count, uint32_t val)
Definition fill.h:50
void pattern_fill_16_aligned(uint16_t *buf, size_t count, uint16_t val)
Definition fill.h:86
Definition byte.h:6
void PatternFill< 1 >(byte *buf, size_t count, const byte *val)
Definition fill.h:44
roo::basic_string_view< CharT, Traits > basic_string_view
Definition string_view.h:8
void PatternFill< 3 >(byte *buf, size_t count, const byte *val)
Definition fill.h:152
size_t count
Definition compare.h:45
void PatternWrite< 1 >(byte *buf, const byte *val)
Definition fill.h:19
void PatternFill< 4 >(byte *buf, size_t count, const byte *val)
Definition fill.h:240
void PatternWrite< 4 >(byte *buf, const byte *val)
Definition fill.h:36
void PatternWrite(byte *buf, const byte *val)
void PatternWrite< 2 >(byte *buf, const byte *val)
Definition fill.h:24
void BitFill(byte *buf, uint32_t offset, size_t count, bool value)
Definition fill.h:266
void PatternWrite< 3 >(byte *buf, const byte *val)
Definition fill.h:29
void PatternFill(byte *buf, size_t count, const byte *val)
roo::byte byte
Definition byte.h:8
void PatternFill< 2 >(byte *buf, size_t count, const byte *val)
Definition fill.h:101
void NibbleFill(byte *buf, uint32_t offset, size_t count, byte value)
Definition fill.h:302