roo_io
API Documentation for roo_io
Loading...
Searching...
No Matches
compare.h
Go to the documentation of this file.
1#pragma once
2
3// Utility methods for fast-comparing memory regions against specified bit
4// pattern fills. The methods optimize performance by reducing the frequency of
5// branching and reading 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 bool PatternCompare(const byte* buf, size_t count, const byte* val);
17
18template <int bytes>
19inline bool PatternCompareAligned(const byte* buf, size_t count,
20 const byte* val);
21
22template <>
23inline bool PatternCompare<1>(const byte* buf, size_t count, const byte* val) {
24 while (count >= 4) {
25 if (buf[0] != *val || buf[1] != *val || buf[2] != *val || buf[3] != *val) {
26 return false;
27 }
28 buf += 4;
29 count -= 4;
30 }
31 while (count-- > 0) {
32 if (*buf++ != *val) return false;
33 }
34 return true;
35}
36
37template <>
38inline bool PatternCompareAligned<1>(const byte* buf, size_t count,
39 const byte* val) {
41}
42
43template <>
45 size_t count,
46 const byte* val) {
47 if (((intptr_t)buf & 1) != 0) {
48 // mis-aligned.
49 const roo::byte v0 = val[0];
50 const roo::byte v1 = val[1];
51 while (count >= 4) {
52 if (buf[0] != v0 || buf[1] != v1 || buf[2] != v0 || buf[3] != v1 ||
53 buf[4] != v0 || buf[5] != v1 || buf[6] != v0 || buf[7] != v1) {
54 return false;
55 }
56 buf += 8;
57 count -= 4;
58 }
59 while (count-- > 0) {
60 if (buf[0] != v0 || buf[1] != v1) return false;
61 buf += 2;
62 }
63 return true;
64 } else {
65 // aligned.
66 uint16_t v;
67 ((byte*)&v)[0] = val[0];
68 ((byte*)&v)[1] = val[1];
69 const uint16_t* buf16 = (const uint16_t*)buf;
70 while (count >= 4) {
71 if (buf16[0] != v || buf16[1] != v || buf16[2] != v || buf16[3] != v) {
72 return false;
73 }
74 buf16 += 4;
75 count -= 4;
76 }
77 while (count-- > 0) {
78 if (*buf16++ != v) return false;
79 }
80 return true;
81 }
82}
83
84template <>
86 const byte* buf, size_t count, const byte* val) {
87 uint16_t v = *(const uint16_t*)val;
88 const uint16_t* buf16 = (const uint16_t*)buf;
89 while (count >= 4) {
90 if (buf16[0] != v || buf16[1] != v || buf16[2] != v || buf16[3] != v) {
91 return false;
92 }
93 buf16 += 4;
94 count -= 4;
95 }
96 while (count-- > 0) {
97 if (*buf16++ != v) return false;
98 }
99 return true;
100}
101
102template <>
103inline __attribute__((always_inline)) bool PatternCompare<3>(const byte* buf,
104 size_t count,
105 const byte* val) {
106 while (count >= 4) {
107 if (buf[0] != val[0] || buf[1] != val[1] || buf[2] != val[2] ||
108 buf[3] != val[0] || buf[4] != val[1] || buf[5] != val[2] ||
109 buf[6] != val[0] || buf[7] != val[1] || buf[8] != val[2] ||
110 buf[9] != val[0] || buf[10] != val[1] || buf[11] != val[2]) {
111 return false;
112 }
113 buf += 12;
114 count -= 4;
115 }
116 while (count-- > 0) {
117 if (buf[0] != val[0] || buf[1] != val[1] || buf[2] != val[2]) return false;
118 buf += 3;
119 }
120 return true;
121}
122
123template <>
125 const byte* buf, size_t count, const byte* val) {
126 return PatternCompare<3>(buf, count, val);
127}
128
129template <>
130inline __attribute__((always_inline)) bool PatternCompare<4>(const byte* buf,
131 size_t count,
132 const byte* val) {
133 if (((intptr_t)buf & 3) != 0) {
134 while (count >= 4) {
135 if (buf[0] != val[0] || buf[1] != val[1] || buf[2] != val[2] ||
136 buf[3] != val[3] || buf[4] != val[0] || buf[5] != val[1] ||
137 buf[6] != val[2] || buf[7] != val[3] || buf[8] != val[0] ||
138 buf[9] != val[1] || buf[10] != val[2] || buf[11] != val[3] ||
139 buf[12] != val[0] || buf[13] != val[1] || buf[14] != val[2] ||
140 buf[15] != val[3]) {
141 return false;
142 }
143 buf += 16;
144 count -= 4;
145 }
146 while (count-- > 0) {
147 if (buf[0] != val[0] || buf[1] != val[1] || buf[2] != val[2] ||
148 buf[3] != val[3])
149 return false;
150 buf += 4;
151 }
152 return true;
153 } else {
154 uint32_t v;
155 ((byte*)&v)[0] = val[0];
156 ((byte*)&v)[1] = val[1];
157 ((byte*)&v)[2] = val[2];
158 ((byte*)&v)[3] = val[3];
159 const uint32_t* buf32 = (const uint32_t*)buf;
160 while (count >= 4) {
161 if (buf32[0] != v || buf32[1] != v || buf32[2] != v || buf32[3] != v) {
162 return false;
163 }
164 buf32 += 4;
165 count -= 4;
166 }
167 while (count-- > 0) {
168 if (*buf32++ != v) return false;
169 }
170 return true;
171 }
172}
173
174template <>
176 const byte* buf, size_t count, const byte* val) {
177 const uint32_t v = (*(const uint32_t*)val);
178 const uint32_t* buf32 = (const uint32_t*)buf;
179 while (count >= 4) {
180 if (buf32[0] != v || buf32[1] != v || buf32[2] != v || buf32[3] != v) {
181 return false;
182 }
183 buf32 += 4;
184 count -= 4;
185 }
186 while (count-- > 0) {
187 if (*buf32++ != v) return false;
188 }
189 return true;
190}
191
192} // namespace roo_io
Definition byte.h:6
bool PatternCompareAligned(const byte *buf, size_t count, const byte *val)
__attribute__((always_inline)) bool PatternCompare< 2 >(const byte *buf
roo::basic_string_view< CharT, Traits > basic_string_view
Definition string_view.h:8
bool PatternCompareAligned< 1 >(const byte *buf, size_t count, const byte *val)
Definition compare.h:38
size_t count
Definition compare.h:45
bool PatternCompare(const byte *buf, size_t count, const byte *val)
bool PatternCompare< 1 >(const byte *buf, size_t count, const byte *val)
Definition compare.h:23