xref: /freebsd/lib/libc/string/swab.c (revision b1bebaaba9b9c0ddfe503c43ca8e9e3917ee2c57)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  * Copyright (c) 2024 rilysh <nightquick@proton.me>
4  */
5 
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/endian.h>
9 
10 void
11 swab(const void * __restrict from, void * __restrict to, ssize_t len)
12 {
13 	const char *f = from;
14 	char *t = to;
15 	uint16_t tmp;
16 
17 	/*
18 	 * POSIX says overlapping copy behavior is undefined, however many
19 	 * applications assume the old FreeBSD and current GNU libc behavior
20 	 * that will swap the bytes correctly when from == to. Reading both bytes
21 	 * and swapping them before writing them back accomplishes this.
22 	 */
23 	while (len > 1) {
24 		memcpy(&tmp, f, 2);
25 		tmp = bswap16(tmp);
26 		memcpy(t, &tmp, 2);
27 
28 		f += 2;
29 		t += 2;
30 		len -= 2;
31 	}
32 }
33