diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-08-25 21:57:28 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-08-25 21:57:28 -0400 |
| commit | 7109035b78ee05302bbdaadc52013b430a030b69 (patch) | |
| tree | ae6d7202dc75f2c799f5fbcad72ccf8b02a954a4 /std/mem.zig | |
| parent | 6cf248ec0824c746fc796905144c8077ccab99cf (diff) | |
| parent | 526338b00fbe1cac19f64832176af3bdf2108a56 (diff) | |
| download | zig-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.zig | 123 |
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); } + |
