xref: /freebsd/lib/libc/string/swab.c (revision 02ebbc781f082df9714e74775700d8c08bac7850)
18a16b7a1SPedro F. Giffuni /*-
2bac2eea1Srilysh  * SPDX-License-Identifier: BSD-2-Clause
3bac2eea1Srilysh  * Copyright (c) 2024 rilysh <nightquick@proton.me>
458f0484fSRodney W. Grimes  */
558f0484fSRodney W. Grimes 
62f5cde3cSTom Rhodes #include <unistd.h>
7*02ebbc78SWarner Losh #include <sys/endian.h>
858f0484fSRodney W. Grimes 
958f0484fSRodney W. Grimes void
swab(const void * __restrict from,void * __restrict to,ssize_t len)102f5cde3cSTom Rhodes swab(const void * __restrict from, void * __restrict to, ssize_t len)
1158f0484fSRodney W. Grimes {
12*02ebbc78SWarner Losh 	const uint16_t *f __aligned(1) = from;
13*02ebbc78SWarner Losh 	uint16_t *t __aligned(1) = to;
1458f0484fSRodney W. Grimes 
15*02ebbc78SWarner Losh 	/*
16*02ebbc78SWarner Losh 	 * POSIX says overlapping copy behavior is undefined, however many
17*02ebbc78SWarner Losh 	 * applications assume the old FreeBSD and current GNU libc behavior
18*02ebbc78SWarner Losh 	 * that will swap the bytes correctly when from == to. Reading both bytes
19*02ebbc78SWarner Losh 	 * and swapping them before writing them back accomplishes this.
20*02ebbc78SWarner Losh 	 */
21bac2eea1Srilysh 	while (len > 1) {
22*02ebbc78SWarner Losh 		*t++ = bswap16(*f++);
23bac2eea1Srilysh 		len -= 2;
2458f0484fSRodney W. Grimes 	}
2558f0484fSRodney W. Grimes }
26