libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
memops.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2017 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include "core/memops.hpp"
25 
26 using namespace libjmmcg;
27 
28 BOOST_AUTO_TEST_SUITE(memops_tests)
29 
30 BOOST_AUTO_TEST_SUITE(string)
31 
32 BOOST_AUTO_TEST_CASE(strchr_char) {
33  constexpr const char a='a';
34  const char string[]="a";
35  BOOST_CHECK_EQUAL(*strchr_opt<a>(string), *std::strchr(string, a));
36  constexpr const char space=' ';
37  char const * const l=strchr_opt<space>(string);
38  char const * const r=std::strchr(string, space);
39  BOOST_CHECK_EQUAL(l, r);
40 }
41 
42 BOOST_AUTO_TEST_CASE(strchr_16) {
43  constexpr const char a='a';
44  const char string[]="thequickbrowfox";
45  char const * const l1=strchr_opt<a>(string);
46  char const * const r1=std::strchr(string, a);
47  BOOST_CHECK_EQUAL(l1, r1);
48  constexpr const char space=' ';
49  char const * const l2=strchr_opt<space>(string);
50  char const * const r2=std::strchr(string, space);
51  BOOST_CHECK_EQUAL(l2, r2);
52 }
53 
54 BOOST_AUTO_TEST_CASE(strchr_32) {
55  constexpr const char a='a';
56  const char string[]="thequickbrownfoxjumpsoverthelaz";
57  char const * const l1=strchr_opt<a>(string);
58  char const * const r1=std::strchr(string, a);
59  BOOST_CHECK_EQUAL(l1, r1);
60  constexpr const char space=' ';
61  char const * const l2=strchr_opt<space>(string);
62  char const * const r2=std::strchr(string, space);
63  BOOST_CHECK_EQUAL(l2, r2);
64 }
65 
66 BOOST_AUTO_TEST_CASE(strchr_48) {
67  constexpr const char a='a';
68  const char string[]="thequickbrownfoxjumpsoverthelazydog1234567890-=";
69  char const * const l1=strchr_opt<a>(string);
70  char const * const r1=std::strchr(string, a);
71  BOOST_CHECK_EQUAL(l1, r1);
72  constexpr const char space=' ';
73  char const * const l2=strchr_opt<space>(string);
74  char const * const r2=std::strchr(string, space);
75  BOOST_CHECK_EQUAL(l2, r2);
76 }
77 
78 BOOST_AUTO_TEST_CASE(strchr_49) {
79  constexpr const char a='a';
80  const char string[]="thequickbrownfoxjumpsoverthelazydog1234567890-=+";
81  char const * const l1=strchr_opt<a>(string);
82  char const * const r1=std::strchr(string, a);
83  BOOST_CHECK_EQUAL(l1, r1);
84  constexpr const char space=' ';
85  char const * const l2=strchr_opt<space>(string);
86  char const * const r2=std::strchr(string, space);
87  BOOST_CHECK_EQUAL(l2, r2);
88 }
89 
90 BOOST_AUTO_TEST_CASE(strstr_small) {
91  const char substr[]="fox";
92  const char string[]="thefox";
93  char const * const l1=strstr_opt(string, substr);
94  char const * const r1=std::strstr(string, substr);
95  BOOST_CHECK_EQUAL(l1, r1);
96  const char substr1[]="foxy";
97  char const * const l2=strstr_opt(string, substr1);
98  char const * const r2=std::strstr(string, substr1);
99  BOOST_CHECK_EQUAL(l2, r2);
100 }
101 
102 BOOST_AUTO_TEST_CASE(strstr_16) {
103  const char substr[]="fox";
104  const char string[]="thequickbrowfox";
105  char const * const l1=strstr_opt(string, substr);
106  char const * const r1=std::strstr(string, substr);
107  BOOST_CHECK_EQUAL(l1, r1);
108  const char substr1[]="foxy";
109  char const * const l2=strstr_opt(string, substr1);
110  char const * const r2=std::strstr(string, substr1);
111  BOOST_CHECK_EQUAL(l2, r2);
112 }
113 
114 BOOST_AUTO_TEST_CASE(strstr_32) {
115  const char substr[]="fox";
116  const char string[]="thequickbrownfoxjumpsoverthelaz";
117  char const * const l1=strstr_opt(string, substr);
118  char const * const r1=std::strstr(string, substr);
119  BOOST_CHECK_EQUAL(l1, r1);
120  const char substr1[]="foxy";
121  char const * const l2=strstr_opt(string, substr1);
122  char const * const r2=std::strstr(string, substr1);
123  BOOST_CHECK_EQUAL(l2, r2);
124 }
125 
126 BOOST_AUTO_TEST_CASE(strstr_48) {
127  const char substr[]="fox";
128  const char string[]="thequickbrownfoxjumpsoverthelazydog1234567890-=";
129  char const * const l1=strstr_opt(string, substr);
130  char const * const r1=std::strstr(string, substr);
131  BOOST_CHECK_EQUAL(l1, r1);
132  const char substr1[]="foxy";
133  char const * const l2=strstr_opt(string, substr1);
134  char const * const r2=std::strstr(string, substr1);
135  BOOST_CHECK_EQUAL(l2, r2);
136 }
137 
138 BOOST_AUTO_TEST_CASE(strstr_49) {
139  const char substr[]="fox";
140  const char string[]="thequickbrownfoxjumpsoverthelazydog1234567890-=+";
141  char const * const l1=strstr_opt(string, substr);
142  char const * const r1=std::strstr(string, substr);
143  BOOST_CHECK_EQUAL(l1, r1);
144  const char substr1[]="foxy";
145  char const * const l2=strstr_opt(string, substr1);
146  char const * const r2=std::strstr(string, substr1);
147  BOOST_CHECK_EQUAL(l2, r2);
148 }
149 
150 BOOST_AUTO_TEST_SUITE_END()
151 
152 BOOST_AUTO_TEST_SUITE(memcpy)
153 
154 /// Create an array that is guaranteed to be mis-aligned.
155 /**
156  Now ASAN reports mis-aligned accesses, [1], which could occur using MOV instructions [2] as in 64-bit mode alignment checking of ring 3 can be enabled. But on Intel & AMD mis-aligned access to memory-operands is not an issue in ring 3, so ubsan is conservative (obeying the Standard).
157 
158  [1] <a href="https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/"/>
159  [2] <a href="https://www.felixcloutier.com/x86/mov"/>
160 */
161 template<std::size_t Sz>
162 struct alignas(std::uint64_t) misalign_array {
163  char misalign;
164  char str[Sz];
165 } __attribute__((__packed__));
166 
167 BOOST_AUTO_TEST_CASE(memcpy_1_byte) {
168  alignas(std::uint64_t) const char src[1]={'f'};
169  alignas(std::uint64_t) char dest[sizeof(src)]={'\0'};
170  memcpy_opt(src, dest);
171  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
172 }
173 
174 BOOST_AUTO_TEST_CASE(memcpy_2_bytes_aligned) {
175  alignas(std::uint64_t) const char src[2]={'f', 'u'};
176  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0'};
177  memcpy_opt(src, dest);
178  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
179 }
180 
181 BOOST_AUTO_TEST_CASE(memcpy_2_bytes_misaligned) {
182  misalign_array<2> src={'\0', {'t', 'h'}};
183  misalign_array<2> dest={'\0', {'\0', '\0'}};
184  memcpy_opt(src.str, dest.str);
185  BOOST_CHECK_EQUAL(std::string(src.str, sizeof(src.str)), std::string(dest.str, sizeof(dest.str)));
186 }
187 
188 BOOST_AUTO_TEST_CASE(memcpy_3_bytes) {
189  alignas(std::uint64_t) const char src[3]={'f', 'u', 'b'};
190  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0'};
191  memcpy_opt(src, dest);
192  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
193 }
194 
195 BOOST_AUTO_TEST_CASE(memcpy_4_bytes_aligned) {
196  alignas(std::uint64_t) const char src[4]={'f', 'u', 'b', 'a'};
197  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0'};
198  memcpy_opt(src, dest);
199  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
200 }
201 
202 BOOST_AUTO_TEST_CASE(memcpy_4_bytes_misaligned) {
203  misalign_array<4> src={'\0', {'t', 'h', 'e', 'q'}};
204  misalign_array<4> dest={'\0', {'\0', '\0', '\0', '\0'}};
205  memcpy_opt(src.str, dest.str);
206  BOOST_CHECK_EQUAL(std::string(src.str, sizeof(src.str)), std::string(dest.str, sizeof(dest.str)));
207 }
208 
209 BOOST_AUTO_TEST_CASE(memcpy_5_bytes) {
210  alignas(std::uint64_t) const char src[5]={'f', 'u', 'b', 'a', 'r'};
211  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0'};
212  memcpy_opt(src, dest);
213  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
214 }
215 
216 BOOST_AUTO_TEST_CASE(memcpy_6_bytes) {
217  alignas(std::uint64_t) const char src[6]={'t', 'h', 'e', 'q', 'u', 'i'};
218  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0'};
219  memcpy_opt(src, dest);
220  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
221 }
222 
223 BOOST_AUTO_TEST_CASE(memcpy_7_bytes) {
224  alignas(std::uint64_t) const char src[7]={'t', 'h', 'e', 'q', 'u', 'i', 'c'};
225  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0'};
226  memcpy_opt(src, dest);
227  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
228 }
229 
230 BOOST_AUTO_TEST_CASE(memcpy_8_bytes_aligned) {
231  alignas(std::uint64_t) const char src[8]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k'};
232  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
233  memcpy_opt(src, dest);
234  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
235 }
236 
237 BOOST_AUTO_TEST_CASE(memcpy_8_bytes_misaligned) {
238  misalign_array<8> src={'\0', {'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k'}};
239  misalign_array<8> dest={'\0', {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}};
240  memcpy_opt(src.str, dest.str);
241  BOOST_CHECK_EQUAL(std::string(src.str, sizeof(src.str)), std::string(dest.str, sizeof(dest.str)));
242 }
243 
244 BOOST_AUTO_TEST_CASE(memcpy_9_bytes) {
245  alignas(std::uint64_t) const char src[9]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b'};
246  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
247  memcpy_opt(src, dest);
248  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
249 }
250 
251 BOOST_AUTO_TEST_CASE(memcpy_10_bytes) {
252  alignas(std::uint64_t) const char src[10]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r'};
253  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
254  memcpy_opt(src, dest);
255  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
256 }
257 
258 BOOST_AUTO_TEST_CASE(memcpy_11_bytes) {
259  alignas(std::uint64_t) const char src[11]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o'};
260  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
261  memcpy_opt(src, dest);
262  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
263 }
264 
265 BOOST_AUTO_TEST_CASE(memcpy_12_bytes) {
266  alignas(std::uint64_t) const char src[12]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w'};
267  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
268  memcpy_opt(src, dest);
269  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
270 }
271 
272 BOOST_AUTO_TEST_CASE(memcpy_13_bytes) {
273  alignas(std::uint64_t) const char src[13]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w', 'n'};
274  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
275  memcpy_opt(src, dest);
276  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
277 }
278 
279 BOOST_AUTO_TEST_CASE(memcpy_14_bytes) {
280  alignas(std::uint64_t) const char src[14]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w', 'n', 'f'};
281  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
282  memcpy_opt(src, dest);
283  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
284 }
285 
286 BOOST_AUTO_TEST_CASE(memcpy_15_bytes) {
287  alignas(std::uint64_t) const char src[15]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w', 'n', 'f', 'o'};
288  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
289  memcpy_opt(src, dest);
290  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
291 }
292 
293 BOOST_AUTO_TEST_CASE(memcpy_16_bytes) {
294  alignas(std::uint64_t) const char src[16]={'t', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w', 'n', 'f', 'o', 'x'};
295  alignas(std::uint64_t) char dest[sizeof(src)]={'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
296  memcpy_opt(src, dest);
297  BOOST_CHECK_EQUAL(std::string(src, sizeof(src)), std::string(dest, sizeof(dest)));
298 }
299 
300 BOOST_AUTO_TEST_SUITE_END()
301 
302 BOOST_AUTO_TEST_SUITE_END()