diff --git a/lib/std/core/bitorder.c3 b/lib/std/core/bitorder.c3 index 43cc52e81..771bb7715 100644 --- a/lib/std/core/bitorder.c3 +++ b/lib/std/core/bitorder.c3 @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::core::bitorder; - +import std::bits; // This module contains types of different endianness. // *BE types represent big-endian types // *LE types represent little-endian types. @@ -87,6 +87,56 @@ bitstruct UInt128LE : uint128 @littleendian uint128 val : 0..127; } +<* + @require $defined(*bytes) : "Pointer must be possible to dereference" + @require types::is_intlike($typeof(*bytes)) : "Type must be an integer or int vector" +*> +macro load_be(bytes) +{ + $if env::BIG_ENDIAN: + return mem::load(bytes, $align: 1); + $else + return bswap(mem::load(bytes, $align: 1)); + $endif +} + +<* + @require $defined(*bytes) : "Pointer must be possible to dereference" + @require types::is_intlike($typeof(*bytes)) : "Type must be an integer or int vector" +*> +macro load_le(bytes) +{ + $if env::BIG_ENDIAN: + return bswap(mem::load(bytes, $align: 1)); + $else + return mem::load(bytes, $align: 1); + $endif +} + +<* + @require types::is_intlike($typeof(value)) : "Type must be an integer or int vector" +*> +macro void store_be(void* dst, value) +{ + $if env::BIG_ENDIAN: + mem::store(($typeof(value)*)dst, value, $align: 1); + $else + mem::store(($typeof(value)*)dst, bswap(value), $align: 1); + $endif +} + +<* + @require types::is_intlike($typeof(value)) : "Type must be an integer or int vector" +*> +macro void store_le(void* dst, value) +{ + $if env::BIG_ENDIAN: + mem::store(($typeof(value)*)dst, bswap(value), $align: 1); + $else + mem::store(($typeof(value)*)dst, value, $align: 1); + $endif +} + <* @require @is_array_or_slice_of_char(bytes) : "argument must be an array, a pointer to an array or a slice of char" @require is_bitorder($Type) : "type must be a bitorder integer" diff --git a/releasenotes.md b/releasenotes.md index 7cf6bfd58..b6cd443af 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -29,6 +29,7 @@ - Add single-byte code page support (DOS/OEM, Windows/ANSI, and ISO/IEC 8859). - Add `array::even`, `array::odd`, and `array::unlace` macros. #2892 - Add discrete and continuous distributions in `std::math::distributions`. +- Add bitorder functions `store_le`, `load_le`, `store_be`, `store_le`. ### Fixes - Add error message if directory with output file name already exists diff --git a/test/unit/stdlib/core/bitorder.c3 b/test/unit/stdlib/core/bitorder.c3 index 3c402cb75..e773f2be4 100644 --- a/test/unit/stdlib/core/bitorder.c3 +++ b/test/unit/stdlib/core/bitorder.c3 @@ -33,6 +33,15 @@ fn void test_read() assert(bitorder::read(bytes[..], ULongLE) == 0x0807060504030201); } +fn void test_load() +{ + char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + assert(bitorder::load_be((short*)&bytes) == 0x0102); + assert(bitorder::load_le((short*)&bytes) == 0x0201); + assert(bitorder::load_be((long*)&bytes) == 0x0102030405060708); + assert(bitorder::load_le((long*)&bytes) == 0x0807060504030201); +} + fn void test_write() { char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; @@ -49,4 +58,41 @@ fn void test_write() ulong x3 = bitorder::read(bytes, ULongBE); bitorder::write(x3, buf[..], ULongBE); assert(bitorder::read(buf, ULongBE) == x3); +} + +fn void test_store() +{ + char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + char[8] buf; + + ushort x1 = bitorder::load_be((ushort*)&bytes); + bitorder::store_be(&buf, x1); + assert(bitorder::read(buf, UShortBE) == x1); + + uint x2 = bitorder::load_be((uint*)&bytes); + bitorder::store_be(&buf, x2); + assert(bitorder::read(buf, UIntBE) == x2); + + ulong x3 = bitorder::load_be((ulong*)&bytes); + bitorder::store_be(&buf, x3); + assert(bitorder::read(buf, ULongBE) == x3); +} + +fn void test_store_le() +{ + char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + char[8] buf; + + ushort x1 = bitorder::load_le((ushort*)&bytes); + bitorder::store_le(&buf, x1); + assert(bitorder::read(buf, UShortLE) == x1); + + uint x2 = bitorder::load_le((uint*)&bytes); + bitorder::store_le(&buf, x2); + assert(bitorder::read(buf, UIntLE) == x2); + + ulong x3 = bitorder::load_le((ulong*)&bytes); + bitorder::store_le(&buf, x3); + assert(bitorder::read(buf, ULongLE) == x3); + } \ No newline at end of file