From 5786df933d37d52d57fef9c28acb9c2c23128d31 Mon Sep 17 00:00:00 2001 From: Josh Wolfe Date: Thu, 30 Nov 2017 11:20:39 -0700 Subject: [PATCH] add mem.readIntLE and readIntBE --- std/mem.zig | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/std/mem.zig b/std/mem.zig index 3cfdb25b35..9d78b1513b 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -180,6 +180,7 @@ test "mem.indexOf" { /// Reads an integer from memory with size equal to bytes.len. /// T specifies the return type, which must be large enough to store /// the result. +/// See also ::readIntBE or ::readIntLE. pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T { if (T.bit_count == 8) { return bytes[0]; @@ -198,6 +199,34 @@ pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T { return result; } +/// Reads a big-endian int of type T from bytes. +/// bytes.len must be exactly @sizeOf(T). +pub fn readIntBE(comptime T: type, bytes: []const u8) -> T { + if (T.is_signed) { + return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); + } + assert(bytes.len == @sizeOf(T)); + var result: T = 0; + {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { + result = (result << 8) | T(bytes[i]); + }} + return result; +} + +/// Reads a little-endian int of type T from bytes. +/// bytes.len must be exactly @sizeOf(T). +pub fn readIntLE(comptime T: type, bytes: []const u8) -> T { + if (T.is_signed) { + return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); + } + assert(bytes.len == @sizeOf(T)); + var result: T = 0; + {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) { + result |= T(bytes[i]) << i * 8; + }} + return result; +} + /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes /// to fill the entire buffer provided. /// value must be an integer. @@ -348,8 +377,12 @@ test "testReadInt" { fn testReadIntImpl() { { const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; - assert(readInt(bytes, u32, true) == 0x12345678); + assert(readInt(bytes, u32, true) == 0x12345678); + assert(readIntBE(u32, bytes) == 0x12345678); + assert(readIntBE(i32, bytes) == 0x12345678); assert(readInt(bytes, u32, false) == 0x78563412); + assert(readIntLE(u32, bytes) == 0x78563412); + assert(readIntLE(i32, bytes) == 0x78563412); } { const buf = []u8{0x00, 0x00, 0x12, 0x34}; @@ -361,6 +394,13 @@ fn testReadIntImpl() { const answer = readInt(buf, u64, false); assert(answer == 0x00003412); } + { + const bytes = []u8{0xff, 0xfe}; + assert(readIntBE(u16, bytes) == 0xfffe); + assert(readIntBE(i16, bytes) == -0x0002); + assert(readIntLE(u16, bytes) == 0xfeff); + assert(readIntLE(i16, bytes) == -0x0101); + } } test "testWriteInt" {