memmove.ha (1627B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 def SZSZ = size(size); 5 def MODSZ = size(size) - 1; 6 7 export fn memmove(dest: *opaque, src: *const opaque, n: size) void = { 8 // implementation adapted from musl libc 9 10 let d = memfunc_ptr { byte = dest: *[*]u8 }; 11 let s = memfunc_ptr { byte = src: *[*]u8 }; 12 13 if (d.uptr == s.uptr) return; 14 // equivalent to n <= abs(src - dest) 15 if (s.uptr - d.uptr - n <= -2*n) return memcpy(dest, src, n); 16 17 if (d.uptr < s.uptr) { 18 // if alignment matches, copy the majority as []size 19 if (s.uptr & MODSZ == d.uptr & MODSZ) { 20 // use u8 until we reach a word boundary 21 for (0 < d.uptr & MODSZ) { 22 if (n == 0) return else n -= 1; 23 d.byte[0] = s.byte[0]; 24 d.uptr += 1; 25 s.uptr += 1; 26 }; 27 for (SZSZ <= n; n -= SZSZ) { 28 d.sz[0] = s.sz[0]; 29 // TODO: should be +=, blocked on compiler bug 30 d.uptr = d.uptr + SZSZ; 31 s.uptr = s.uptr + SZSZ; 32 }; 33 }; 34 for (0 < n; n -= 1) { 35 d.byte[0] = s.byte[0]; 36 d.uptr += 1; 37 s.uptr += 1; 38 }; 39 } else { 40 d.uptr = d.uptr + n; 41 s.uptr = s.uptr + n; 42 // if alignment matches, copy the majority as []size 43 if (s.uptr & MODSZ == d.uptr & MODSZ) { 44 // use u8 until we reach a word boundary 45 for (0 < d.uptr & MODSZ) { 46 if (n == 0) return else n -= 1; 47 d.uptr -= 1; 48 s.uptr -= 1; 49 d.byte[0] = s.byte[0]; 50 }; 51 for (SZSZ <= n; n -= SZSZ) { 52 // TODO: should be -=, blocked on compiler bug 53 d.uptr = d.uptr - SZSZ; 54 s.uptr = s.uptr - SZSZ; 55 d.sz[0] = s.sz[0]; 56 }; 57 }; 58 for (0 < n; n -= 1) { 59 d.uptr -= 1; 60 s.uptr -= 1; 61 d.byte[0] = s.byte[0]; 62 }; 63 }; 64 };