1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5test "memmove and memset intrinsics" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10
11 try testMemmoveMemset();
12 try comptime testMemmoveMemset();
13}
14
15fn testMemmoveMemset() !void {
16 var foo: [20]u8 = undefined;
17
18 @memset(foo[0..10], 'A');
19 @memset(foo[10..20], 'B');
20
21 try expect(foo[0] == 'A');
22 try expect(foo[11] == 'B');
23 try expect(foo[19] == 'B');
24
25 @memmove(foo[10..20], foo[0..10]);
26
27 try expect(foo[0] == 'A');
28 try expect(foo[11] == 'A');
29 try expect(foo[19] == 'A');
30}
31
32test "@memmove with both operands single-ptr-to-array, one is null-terminated" {
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
37
38 try testMemmoveBothSinglePtrArrayOneIsNullTerminated();
39 try comptime testMemmoveBothSinglePtrArrayOneIsNullTerminated();
40}
41
42fn testMemmoveBothSinglePtrArrayOneIsNullTerminated() !void {
43 var buf: [100]u8 = undefined;
44 const suffix = "hello";
45 @memmove(buf[buf.len - suffix.len ..], suffix);
46 try expect(buf[95] == 'h');
47 try expect(buf[96] == 'e');
48 try expect(buf[97] == 'l');
49 try expect(buf[98] == 'l');
50 try expect(buf[99] == 'o');
51
52 const start = buf.len - suffix.len - 3;
53 const end = start + suffix.len;
54 @memmove(buf[start..end], buf[buf.len - suffix.len ..]);
55 try expect(buf[92] == 'h');
56 try expect(buf[93] == 'e');
57 try expect(buf[94] == 'l');
58 try expect(buf[95] == 'l');
59 try expect(buf[96] == 'o');
60 try expect(buf[97] == 'l');
61 try expect(buf[98] == 'l');
62 try expect(buf[99] == 'o');
63
64 @memmove(buf[start + 2 .. end + 2], buf[start..end]);
65 try expect(buf[92] == 'h');
66 try expect(buf[93] == 'e');
67 try expect(buf[94] == 'h');
68 try expect(buf[95] == 'e');
69 try expect(buf[96] == 'l');
70 try expect(buf[97] == 'l');
71 try expect(buf[98] == 'o');
72 try expect(buf[99] == 'o');
73}
74
75test "@memmove dest many pointer" {
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
80
81 try testMemmoveDestManyPtr();
82 try comptime testMemmoveDestManyPtr();
83}
84
85fn testMemmoveDestManyPtr() !void {
86 var str = "hello".*;
87 var buf: [8]u8 = undefined;
88 var len: usize = 5;
89 _ = &len;
90 @memmove(@as([*]u8, @ptrCast(&buf)), @as([*]const u8, @ptrCast(&str))[0..len]);
91 try expect(buf[0] == 'h');
92 try expect(buf[1] == 'e');
93 try expect(buf[2] == 'l');
94 try expect(buf[3] == 'l');
95 try expect(buf[4] == 'o');
96 @memmove(buf[3..].ptr, buf[0..len]);
97 try expect(buf[0] == 'h');
98 try expect(buf[1] == 'e');
99 try expect(buf[2] == 'l');
100 try expect(buf[3] == 'h');
101 try expect(buf[4] == 'e');
102 try expect(buf[5] == 'l');
103 try expect(buf[6] == 'l');
104 try expect(buf[7] == 'o');
105 @memmove(buf[2..7].ptr, buf[3 .. len + 3]);
106 try expect(buf[0] == 'h');
107 try expect(buf[1] == 'e');
108 try expect(buf[2] == 'h');
109 try expect(buf[3] == 'e');
110 try expect(buf[4] == 'l');
111 try expect(buf[5] == 'l');
112 try expect(buf[6] == 'o');
113 try expect(buf[7] == 'o');
114}
115
116test "@memmove slice" {
117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
121 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
122
123 try testMemmoveSlice();
124 try comptime testMemmoveSlice();
125}
126
127fn testMemmoveSlice() !void {
128 var buf: [8]u8 = undefined;
129 const dst1: []u8 = buf[0..5];
130 const dst2: []u8 = buf[3..8];
131 const dst3: []u8 = buf[2..7];
132 const src: []const u8 = "hello";
133 @memmove(dst1, src);
134 try expect(buf[0] == 'h');
135 try expect(buf[1] == 'e');
136 try expect(buf[2] == 'l');
137 try expect(buf[3] == 'l');
138 try expect(buf[4] == 'o');
139 @memmove(dst2, dst1);
140 try expect(buf[0] == 'h');
141 try expect(buf[1] == 'e');
142 try expect(buf[2] == 'l');
143 try expect(buf[3] == 'h');
144 try expect(buf[4] == 'e');
145 try expect(buf[5] == 'l');
146 try expect(buf[6] == 'l');
147 try expect(buf[7] == 'o');
148 @memmove(dst3, dst2);
149 try expect(buf[0] == 'h');
150 try expect(buf[1] == 'e');
151 try expect(buf[2] == 'h');
152 try expect(buf[3] == 'e');
153 try expect(buf[4] == 'l');
154 try expect(buf[5] == 'l');
155 try expect(buf[6] == 'o');
156 try expect(buf[7] == 'o');
157}
158
159comptime {
160 const S = struct {
161 buffer: [8]u8 = undefined,
162 fn set(self: *@This(), items: []const u8) void {
163 @memmove(self.buffer[0..items.len], items);
164 @memmove(self.buffer[3..], self.buffer[0..items.len]);
165 @memmove(self.buffer[2 .. 2 + items.len], self.buffer[3..]);
166 }
167 };
168
169 var s = S{};
170 s.set("hello");
171 if (!std.mem.eql(u8, s.buffer[0..8], "hehelloo")) @compileError("bad");
172}