diff --git a/lib/std/core/bitorder.c3 b/lib/std/core/bitorder.c3 index 6238ac534..51bab6dc4 100644 --- a/lib/std/core/bitorder.c3 +++ b/lib/std/core/bitorder.c3 @@ -87,3 +87,91 @@ bitstruct UInt128LE : uint128 @littleendian uint128 val : 0..127; } +/** + * @require is_array_or_sub_of_char(bytes) "argument must be an array, a pointer to an array or a subarray of char" + * @require is_bitorder($Type) "type must be a bitorder integer" + **/ +macro read(bytes, $Type) +{ + char[] s; + $switch ($typeof(bytes).kindof) + $case POINTER: + s = (*bytes)[:$Type.sizeof]; + $default: + s = bytes[:$Type.sizeof]; + $endswitch + return bitcast(*(char[$Type.sizeof]*)s.ptr, $Type).val; +} + +/** + * @require is_arrayptr_or_sub_of_char(bytes) "argument must be a pointer to an array or a subarray of char" + * @require is_bitorder($Type) "type must be a bitorder integer" + **/ +macro write(x, bytes, $Type) +{ + char[] s; + $switch ($typeof(bytes).kindof) + $case POINTER: + s = (*bytes)[:$Type.sizeof]; + $default: + s = bytes[:$Type.sizeof]; + $endswitch + *($typeof(x)*)s.ptr = bitcast(x, $Type).val; +} + +macro is_bitorder($Type) +{ + $switch ($Type) + $case UShortLE: + $case ShortLE: + $case UIntLE: + $case IntLE: + $case ULongLE: + $case LongLE: + $case UInt128LE: + $case Int128LE: + $case UShortBE: + $case ShortBE: + $case UIntBE: + $case IntBE: + $case ULongBE: + $case LongBE: + $case UInt128BE: + $case Int128BE: + return true; + $endswitch + return false; +} + +macro bool is_array_or_sub_of_char(bytes) +{ + $switch ($typeof(bytes).kindof) + $case POINTER: + var $Inner = $typefrom($typeof(bytes).inner); + $if $Inner.kindof == ARRAY: + var $Inner2 = $typefrom($Inner.inner); + return $Inner2.typeid == char.typeid; + $endif + $case ARRAY: + $case SUBARRAY: + var $Inner = $typefrom($typeof(bytes).inner); + return $Inner.typeid == char.typeid; + $endswitch + return false; +} + +macro bool is_arrayptr_or_sub_of_char(bytes) +{ + $switch ($typeof(bytes).kindof) + $case POINTER: + var $Inner = $typefrom($typeof(bytes).inner); + $if $Inner.kindof == ARRAY: + var $Inner2 = $typefrom($Inner.inner); + return $Inner2.typeid == char.typeid; + $endif + $case SUBARRAY: + var $Inner = $typefrom($typeof(bytes).inner); + return $Inner.typeid == char.typeid; + $endswitch + return false; +} \ No newline at end of file diff --git a/test/unit/stdlib/core/bitorder.c3 b/test/unit/stdlib/core/bitorder.c3 new file mode 100644 index 000000000..aaca67af2 --- /dev/null +++ b/test/unit/stdlib/core/bitorder.c3 @@ -0,0 +1,45 @@ +module std::core::bitorder @test; + +fn void! test_read() +{ + char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + + assert(bitorder::read(bytes, UShortBE) == 0x0102); + assert(bitorder::read(bytes, UShortLE) == 0x0201); + assert(bitorder::read(bytes, UIntBE) == 0x01020304); + assert(bitorder::read(bytes, UIntLE) == 0x04030201); + assert(bitorder::read(bytes, ULongBE) == 0x0102030405060708); + assert(bitorder::read(bytes, ULongLE) == 0x0807060504030201); + + assert(bitorder::read(&bytes, UShortBE) == 0x0102); + assert(bitorder::read(&bytes, UShortLE) == 0x0201); + assert(bitorder::read(&bytes, UIntBE) == 0x01020304); + assert(bitorder::read(&bytes, UIntLE) == 0x04030201); + assert(bitorder::read(&bytes, ULongBE) == 0x0102030405060708); + assert(bitorder::read(&bytes, ULongLE) == 0x0807060504030201); + + assert(bitorder::read(bytes[:], UShortBE) == 0x0102); + assert(bitorder::read(bytes[:], UShortLE) == 0x0201); + assert(bitorder::read(bytes[:], UIntBE) == 0x01020304); + assert(bitorder::read(bytes[:], UIntLE) == 0x04030201); + assert(bitorder::read(bytes[:], ULongBE) == 0x0102030405060708); + assert(bitorder::read(bytes[:], ULongLE) == 0x0807060504030201); +} + +fn void! test_write() +{ + char[*] bytes = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + char[8] buf; + + ushort x1 = bitorder::read(bytes, UShortBE); + bitorder::write(x1, &buf, UShortBE); + assert(bitorder::read(buf, UShortBE) == x1); + + uint x2 = bitorder::read(bytes, UIntBE); + bitorder::write(x2, buf[:], UIntBE); + assert(bitorder::read(buf, UIntBE) == x2); + + ulong x3 = bitorder::read(bytes, ULongBE); + bitorder::write(x3, buf[:], ULongBE); + assert(bitorder::read(buf, ULongBE) == x3); +} \ No newline at end of file