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}