Skip to content

Commit

Permalink
- Add read/write to stream with big endian ints.
Browse files Browse the repository at this point in the history
- Move accidently hidden "wrap_bytes".
  • Loading branch information
lerno committed Oct 3, 2024
1 parent 02e9bfa commit fa4ca79
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 7 deletions.
7 changes: 0 additions & 7 deletions lib/std/io/io.c3
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,3 @@ fn File* stdin()
return &stdin_file;
}

/**
* Wrap bytes for reading using io functions.
**/
fn ByteReader wrap_bytes(char[] bytes)
{
return { bytes, 0 };
}
201 changes: 201 additions & 0 deletions lib/std/io/stream.c3
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,205 @@ macro usz! write_varint(stream, x)
}
buffer[i] = (char)x;
return write_all(stream, buffer[:i + 1]);
}

/**
* @require @is_instream(stream)
**/
macro ushort! read_be_ushort(stream)
{
char hi_byte = stream.read_byte()!;
char lo_byte = stream.read_byte()!;
return (ushort)(hi_byte << 8 | lo_byte);
}

/**
* @require @is_instream(stream)
**/
macro short! read_be_short(stream)
{
return read_be_ushort(stream);
}

/**
* @require @is_outstream(stream)
**/
macro void! write_be_short(stream, ushort s)
{
stream.write_byte((char)(s >> 8))!;
stream.write_byte((char)s)!;
}

/**
* @require @is_instream(stream)
**/
macro uint! read_be_uint(stream)
{
uint val = stream.read_byte()! << 24;
val += stream.read_byte()! << 16;
val += stream.read_byte()! << 8;
return val + stream.read_byte()!;
}

/**
* @require @is_instream(stream)
**/
macro int! read_be_int(stream)
{
return read_be_uint(stream);
}

/**
* @require @is_outstream(stream)
**/
macro void! write_be_int(stream, uint s)
{
stream.write_byte((char)(s >> 24))!;
stream.write_byte((char)(s >> 16))!;
stream.write_byte((char)(s >> 8))!;
stream.write_byte((char)s)!;
}

/**
* @require @is_instream(stream)
**/
macro ulong! read_be_ulong(stream)
{
ulong val = (ulong)stream.read_byte()! << 56;
val += (ulong)stream.read_byte()! << 48;
val += (ulong)stream.read_byte()! << 40;
val += (ulong)stream.read_byte()! << 32;
val += (ulong)stream.read_byte()! << 24;
val += (ulong)stream.read_byte()! << 16;
val += (ulong)stream.read_byte()! << 8;
return val + stream.read_byte()!;
}

/**
* @require @is_instream(stream)
**/
macro long! read_be_long(stream)
{
return read_be_ulong(stream);
}

/**
* @require @is_outstream(stream)
**/
macro void! write_be_long(stream, ulong s)
{
stream.write_byte((char)(s >> 56))!;
stream.write_byte((char)(s >> 48))!;
stream.write_byte((char)(s >> 40))!;
stream.write_byte((char)(s >> 32))!;
stream.write_byte((char)(s >> 24))!;
stream.write_byte((char)(s >> 16))!;
stream.write_byte((char)(s >> 8))!;
stream.write_byte((char)s)!;
}

/**
* @require @is_instream(stream)
**/
macro uint128! read_be_uint128(stream)
{
uint128 val = (uint128)stream.read_byte()! << 120;
val += (uint128)stream.read_byte()! << 112;
val += (uint128)stream.read_byte()! << 104;
val += (uint128)stream.read_byte()! << 96;
val += (uint128)stream.read_byte()! << 88;
val += (uint128)stream.read_byte()! << 80;
val += (uint128)stream.read_byte()! << 72;
val += (uint128)stream.read_byte()! << 64;
val += (uint128)stream.read_byte()! << 56;
val += (uint128)stream.read_byte()! << 48;
val += (uint128)stream.read_byte()! << 40;
val += (uint128)stream.read_byte()! << 32;
val += (uint128)stream.read_byte()! << 24;
val += (uint128)stream.read_byte()! << 16;
val += (uint128)stream.read_byte()! << 8;
return val + stream.read_byte()!;
}

/**
* @require @is_instream(stream)
**/
macro int128! read_be_int128(stream)
{
return read_be_uint128(stream);
}

/**
* @require @is_outstream(stream)
**/
macro void! write_be_int128(stream, uint128 s)
{
stream.write_byte((char)(s >> 120))!;
stream.write_byte((char)(s >> 112))!;
stream.write_byte((char)(s >> 104))!;
stream.write_byte((char)(s >> 96))!;
stream.write_byte((char)(s >> 88))!;
stream.write_byte((char)(s >> 80))!;
stream.write_byte((char)(s >> 72))!;
stream.write_byte((char)(s >> 64))!;
stream.write_byte((char)(s >> 56))!;
stream.write_byte((char)(s >> 48))!;
stream.write_byte((char)(s >> 40))!;
stream.write_byte((char)(s >> 32))!;
stream.write_byte((char)(s >> 24))!;
stream.write_byte((char)(s >> 16))!;
stream.write_byte((char)(s >> 8))!;
stream.write_byte((char)s)!;
}

/**
* @require @is_outstream(stream)
* @require data.len < 256 "Data exceeded 255"
**/
macro usz! write_tiny_bytearray(stream, char[] data)
{
stream.write_byte((char)data.len)!;
return stream.write(data) + 1;
}

/**
* @require @is_instream(stream)
**/
macro char[]! read_tiny_bytearray(stream, Allocator allocator)
{
int len = stream.read_byte()!;
if (!len) return {};
char[] data = allocator::alloc_array(allocator, char, len);
io::read_all(stream, data)!;
return data;
}

/**
* @require @is_outstream(stream)
* @require data.len < 0x1000 "Data exceeded 65535"
**/
macro usz! write_short_bytearray(stream, char[] data)
{
io::write_be_short(stream, (ushort)data.len)!;
return stream.write(data) + 2;
}

/**
* @require @is_instream(stream)
**/
macro char[]! read_short_bytearray(stream, Allocator allocator)
{
int len = io::read_be_ushort(stream)!;
if (!len) return {};
char[] data = allocator::alloc_array(allocator, char, len);
io::read_all(stream, data)!;
return data;
}

/**
* Wrap bytes for reading using io functions.
**/
fn ByteReader wrap_bytes(char[] bytes)
{
return { bytes, 0 };
}
2 changes: 2 additions & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

### Stdlib changes
- Remove unintended print of `char[]` as String
- Add read/write to stream with big endian ints.
- Move accidently hidden "wrap_bytes".

## 0.6.3 Change list

Expand Down
87 changes: 87 additions & 0 deletions test/unit/stdlib/io/stream.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
module std::io @test;

fn void read_ushort_test()
{
ByteReader reader = io::wrap_bytes({0x34, 0x8a});
assert(io::read_be_ushort(&reader)!! == 0x348a);
}

fn void read_uint_test()
{
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc});
assert(io::read_be_uint(&reader)!! == 0x348aefcc);
}

fn void read_ulong_test()
{
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc});
assert(io::read_be_ulong(&reader)!! == 0x348aefcc348aefcc);
}

fn void read_uint128_test()
{
ByteReader reader = io::wrap_bytes({0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc, 0x34, 0x8a, 0xef, 0xcc});
assert(io::read_be_uint128(&reader)!! == 0x348aefcc348aefcc348aefcc348aefcc);
}

fn void write_ushort_test()
{
ByteWriter bw;
bw.temp_init();
io::write_be_short(&bw, 0x348a)!!;
assert(bw.str_view() == &&x'348a');
}

fn void write_uint_test()
{
ByteWriter bw;
bw.temp_init();
io::write_be_int(&bw, 0x3421348a)!!;
assert(bw.str_view() == &&x'3421348a');
}

fn void write_ulong_test()
{
ByteWriter bw;
bw.temp_init();
io::write_be_long(&bw, 0xaabbccdd3421348a)!!;
assert(bw.str_view() == &&x'aabbccdd3421348a');
}

fn void write_uint128_test()
{
ByteWriter bw;
bw.temp_init();
io::write_be_int128(&bw, 0xaabbccdd3421348aaabbccdd3421348a)!!;
assert(bw.str_view() == &&x'aabbccdd3421348aaabbccdd3421348a');
}

fn void write_tiny_bytearray_test()
{
ByteWriter bw;
bw.temp_init();
io::write_tiny_bytearray(&bw, &&x"aabbcc00112233")!!;
assert(bw.str_view() == &&x'07aabbcc00112233');
}

fn void write_short_bytearray_test()
{
ByteWriter bw;
bw.temp_init();
io::write_short_bytearray(&bw, &&x"aabbcc00112233")!!;
assert(bw.str_view() == &&x'0007aabbcc00112233');
}

fn void read_tiny_bytearray_test()
{
ByteReader reader = io::wrap_bytes(&&x'07aabbcc00112233');
char[] read = io::read_tiny_bytearray(&reader, allocator: allocator::heap())!;
assert(read == &&x'aabbcc00112233');
}

fn void read_short_bytearray_test()
{
ByteReader reader = io::wrap_bytes(&&x'0007aabbcc00112233');
char[] read = io::read_short_bytearray(&reader, allocator: allocator::heap())!;
assert(read == &&x'aabbcc00112233');
}

0 comments on commit fa4ca79

Please sign in to comment.