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