1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;
const assert = std.debug.assert;
test "memcpy and memset intrinsics" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMemcpyMemset();
try comptime testMemcpyMemset();
}
fn testMemcpyMemset() !void {
var foo: [20]u8 = undefined;
var bar: [20]u8 = undefined;
@memset(&foo, 'A');
@memcpy(&bar, &foo);
try expect(bar[0] == 'A');
try expect(bar[11] == 'A');
try expect(bar[19] == 'A');
}
test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMemcpyBothSinglePtrArrayOneIsNullTerminated();
try comptime testMemcpyBothSinglePtrArrayOneIsNullTerminated();
}
fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void {
var buf: [100]u8 = undefined;
const suffix = "hello";
@memcpy(buf[buf.len - suffix.len ..], suffix);
try expect(buf[95] == 'h');
try expect(buf[96] == 'e');
try expect(buf[97] == 'l');
try expect(buf[98] == 'l');
try expect(buf[99] == 'o');
}
test "@memcpy dest many pointer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMemcpyDestManyPtr();
try comptime testMemcpyDestManyPtr();
}
fn testMemcpyDestManyPtr() !void {
var str = "hello".*;
var buf: [5]u8 = undefined;
var len: usize = 5;
_ = &len;
@memcpy(@as([*]u8, @ptrCast(&buf)), @as([*]const u8, @ptrCast(&str))[0..len]);
try expect(buf[0] == 'h');
try expect(buf[1] == 'e');
try expect(buf[2] == 'l');
try expect(buf[3] == 'l');
try expect(buf[4] == 'o');
}
test "@memcpy C pointer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMemcpyCPointer();
try comptime testMemcpyCPointer();
}
fn testMemcpyCPointer() !void {
const src = "hello";
var buf: [5]u8 = undefined;
@memcpy(@as([*c]u8, &buf), src);
try expect(buf[0] == 'h');
try expect(buf[1] == 'e');
try expect(buf[2] == 'l');
try expect(buf[3] == 'l');
try expect(buf[4] == 'o');
}
test "@memcpy slice" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try testMemcpySlice();
try comptime testMemcpySlice();
}
fn testMemcpySlice() !void {
var buf: [5]u8 = undefined;
const dst: []u8 = &buf;
const src: []const u8 = "hello";
@memcpy(dst, src);
try expect(buf[0] == 'h');
try expect(buf[1] == 'e');
try expect(buf[2] == 'l');
try expect(buf[3] == 'l');
try expect(buf[4] == 'o');
}
comptime {
const S = struct {
buffer: [8]u8 = undefined,
fn set(self: *@This(), items: []const u8) void {
@memcpy(self.buffer[0..items.len], items);
}
};
var s = S{};
s.set("hello");
if (!std.mem.eql(u8, s.buffer[0..5], "hello")) @compileError("bad");
}
test "@memcpy comptime-only type" {
const in: [4]type = .{ u8, u16, u32, u64 };
comptime var out: [4]type = undefined;
@memcpy(&out, &in);
comptime assert(out[0] == u8);
comptime assert(out[1] == u16);
comptime assert(out[2] == u32);
comptime assert(out[3] == u64);
}
test "@memcpy zero-bit type with aliasing" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn doTheTest() void {
var buf: [3]void = @splat({});
const slice: []void = &buf;
// These two pointers are the same, but it's still not considered aliasing because
// the input and output slices both correspond to zero bits of memory.
@memcpy(slice, slice);
comptime assert(buf[0] == {});
comptime assert(buf[1] == {});
comptime assert(buf[2] == {});
}
};
S.doTheTest();
comptime S.doTheTest();
}
test "@memcpy with sentinel" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn doTheTest() void {
const field = @typeInfo(struct { a: u32 }).@"struct".fields[0];
var buffer: [field.name.len]u8 = undefined;
@memcpy(&buffer, field.name);
}
};
S.doTheTest();
comptime S.doTheTest();
}
test "@memcpy no sentinel source into sentinel destination" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const S = struct {
fn doTheTest() void {
const src: []const u8 = &.{ 1, 2, 3 };
comptime var dest_buf: [3:0]u8 = @splat(0);
const dest: [:0]u8 = &dest_buf;
@memcpy(dest, src);
}
};
S.doTheTest();
comptime S.doTheTest();
}
|