aboutsummaryrefslogtreecommitdiff
path: root/std/mem.zig
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-08-25 21:57:28 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-08-25 21:57:28 -0400
commit7109035b78ee05302bbdaadc52013b430a030b69 (patch)
treeae6d7202dc75f2c799f5fbcad72ccf8b02a954a4 /std/mem.zig
parent6cf248ec0824c746fc796905144c8077ccab99cf (diff)
parent526338b00fbe1cac19f64832176af3bdf2108a56 (diff)
downloadzig-7109035b78ee05302bbdaadc52013b430a030b69.tar.gz
zig-7109035b78ee05302bbdaadc52013b430a030b69.zip
Merge remote-tracking branch 'origin/master' into llvm7
Diffstat (limited to 'std/mem.zig')
-rw-r--r--std/mem.zig123
1 files changed, 116 insertions, 7 deletions
diff --git a/std/mem.zig b/std/mem.zig
index 43961a6d14..4390f8ad5b 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -135,6 +135,12 @@ pub const Allocator = struct {
}
};
+pub const Compare = enum {
+ LessThan,
+ Equal,
+ GreaterThan,
+};
+
/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
/// dest.ptr must be <= src.ptr.
@@ -169,16 +175,64 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
d.* = value;
}
-/// Returns true if lhs < rhs, false otherwise
-pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
+pub fn secureZero(comptime T: type, s: []T) void {
+ // NOTE: We do not use a volatile slice cast here since LLVM cannot
+ // see that it can be replaced by a memset.
+ const ptr = @ptrCast([*]volatile u8, s.ptr);
+ const length = s.len * @sizeOf(T);
+ @memset(ptr, 0, length);
+}
+
+test "mem.secureZero" {
+ var a = []u8{0xfe} ** 8;
+ var b = []u8{0xfe} ** 8;
+
+ set(u8, a[0..], 0);
+ secureZero(u8, b[0..]);
+
+ assert(eql(u8, a[0..], b[0..]));
+}
+
+pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
const n = math.min(lhs.len, rhs.len);
var i: usize = 0;
while (i < n) : (i += 1) {
- if (lhs[i] == rhs[i]) continue;
- return lhs[i] < rhs[i];
+ if (lhs[i] == rhs[i]) {
+ continue;
+ } else if (lhs[i] < rhs[i]) {
+ return Compare.LessThan;
+ } else if (lhs[i] > rhs[i]) {
+ return Compare.GreaterThan;
+ } else {
+ unreachable;
+ }
}
- return lhs.len < rhs.len;
+ if (lhs.len == rhs.len) {
+ return Compare.Equal;
+ } else if (lhs.len < rhs.len) {
+ return Compare.LessThan;
+ } else if (lhs.len > rhs.len) {
+ return Compare.GreaterThan;
+ }
+ unreachable;
+}
+
+test "mem.compare" {
+ assert(compare(u8, "abcd", "bee") == Compare.LessThan);
+ assert(compare(u8, "abc", "abc") == Compare.Equal);
+ assert(compare(u8, "abc", "abc0") == Compare.LessThan);
+ assert(compare(u8, "", "") == Compare.Equal);
+ assert(compare(u8, "", "a") == Compare.LessThan);
+}
+
+/// Returns true if lhs < rhs, false otherwise
+pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
+ var result = compare(T, lhs, rhs);
+ if (result == Compare.LessThan) {
+ return true;
+ } else
+ return false;
}
test "mem.lessThan" {
@@ -198,6 +252,20 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
return true;
}
+pub fn len(comptime T: type, ptr: [*]const T) usize {
+ var count: usize = 0;
+ while (ptr[count] != 0) : (count += 1) {}
+ return count;
+}
+
+pub fn toSliceConst(comptime T: type, ptr: [*]const T) []const T {
+ return ptr[0..len(T, ptr)];
+}
+
+pub fn toSlice(comptime T: type, ptr: [*]T) []T {
+ return ptr[0..len(T, ptr)];
+}
+
/// Returns true if all elements in a slice are equal to the scalar value provided
pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
for (slice) |item| {
@@ -541,7 +609,7 @@ pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
}
}
- return buf[0..buf_index];
+ return allocator.shrink(u8, buf, buf_index);
}
test "mem.join" {
@@ -611,10 +679,38 @@ test "testWriteInt" {
comptime testWriteIntImpl();
}
fn testWriteIntImpl() void {
- var bytes: [4]u8 = undefined;
+ var bytes: [8]u8 = undefined;
+
+ writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
+ assert(eql(u8, bytes, []u8{
+ 0x12,
+ 0x34,
+ 0x56,
+ 0x78,
+ 0xCA,
+ 0xFE,
+ 0xBA,
+ 0xBE,
+ }));
+
+ writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
+ assert(eql(u8, bytes, []u8{
+ 0x12,
+ 0x34,
+ 0x56,
+ 0x78,
+ 0xCA,
+ 0xFE,
+ 0xBA,
+ 0xBE,
+ }));
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
0x12,
0x34,
0x56,
@@ -627,12 +723,20 @@ fn testWriteIntImpl() void {
0x34,
0x56,
0x78,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
}));
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{
0x00,
0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
0x12,
0x34,
}));
@@ -643,6 +747,10 @@ fn testWriteIntImpl() void {
0x12,
0x00,
0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
}));
}
@@ -755,3 +863,4 @@ pub fn endianSwap(comptime T: type, x: T) T {
test "std.mem.endianSwap" {
assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
}
+