diff --git a/main.v b/main.v index 7a736fa..4e6fa58 100644 --- a/main.v +++ b/main.v @@ -3,24 +3,29 @@ import os // BITS struct Bits { - mut: - bytes []u8 - current u8 - count u8 +mut: + file os.File + buffer []u8 + current u8 + count u8 } fn write(mut b Bits, value u8) { b.current = b.current | ((value & 1) << b.count) b.count++ if b.count == 8 { - b.bytes << b.current + b.buffer << b.current + if b.buffer.len >= 1048576 { + b.file.write(b.buffer) or { panic(err) } + b.buffer.clear() + } b.current = 0 b.count = 0 } } fn write_lsb(mut b Bits, value u8, length u8) { - for i in 0..length { + for i in 0 .. length { write(mut b, (value >> i) & 1) } } @@ -35,7 +40,11 @@ fn write_msb(mut b Bits, code u16, length u16) { fn flush(mut b Bits) { if b.count > 0 { - b.bytes << b.current + b.buffer << b.current + if b.buffer.len >= 1048576 { + b.file.write(b.buffer) or { panic(err) } + b.buffer.clear() + } b.current = 0 b.count = 0 } @@ -43,7 +52,11 @@ fn flush(mut b Bits) { fn write_byte(mut b Bits, value u8) { flush(mut b) - b.bytes << value + b.buffer << value + if b.buffer.len >= 1048576 { + b.file.write(b.buffer) or { panic(err) } + b.buffer.clear() + } } fn write_u32(mut b Bits, value u32) { @@ -57,13 +70,13 @@ fn write_u32(mut b Bits, value u32) { // GZIP fn write_gzip_header(mut b Bits) { - write_byte(mut b, 0x1f) // MAGIC - write_byte(mut b, 0x8b) // BYTES - write_byte(mut b, 0x08) // COMPRESSION (8, DEFLATE) - write_byte(mut b, 0x00) // FLAG (0, NO FIELDS) - write_u32(mut b, 0) // CREATION TIME (FOFERK WAS CREATED AT THE DAWN OF TIME) - write_byte(mut b, 0x00) // XFL (0, SOME SPECIAL COMPRESSION THING, HAS TO BE LIKE THAT) - write_byte(mut b, 0x03) // OS (3, UNIX) + write_byte(mut b, 0x1f) // MAGIC + write_byte(mut b, 0x8b) // BYTES + write_byte(mut b, 0x08) // COMPRESSION (8, DEFLATE) + write_byte(mut b, 0x00) // FLAG (0, NO FIELDS) + write_u32(mut b, 0) // CREATION TIME (FOFERK WAS CREATED AT THE DAWN OF TIME) + write_byte(mut b, 0x00) // XFL (0, SOME SPECIAL COMPRESSION THING, HAS TO BE LIKE THAT) + write_byte(mut b, 0x03) // OS (3, UNIX) } // DEFLATE @@ -83,8 +96,13 @@ fn write_foferk(mut b Bits) { write_msb(mut b, 0x50, 8) // ' ' + 30 } -fn write_tokens(mut b Bits, repeat int) { +fn write_tokens(mut b Bits, repeat i64) { mut remaining := (repeat - 1) * 7 + total := remaining + + mut next_log := i64(0) + mut written := i64(0) + log_step := if total / 10000 == 0 { i64(1) } else { total / 10000 } for remaining >= 252 { write_msb(mut b, 0xC4, 8) @@ -92,6 +110,14 @@ fn write_tokens(mut b Bits, repeat int) { write_msb(mut b, 0x05, 5) write_lsb(mut b, 0x00, 1) remaining -= 252 + written += 252 + + if written >= next_log { + percent := f64(written) / f64(total) * 100.0 + print('\r${percent:6.2f}% foferk') + os.flush() + next_log += log_step + } } for remaining >= 7 { @@ -118,23 +144,24 @@ fn write_tokens(mut b Bits, repeat int) { write_msb(mut b, 0x05, 5) write_lsb(mut b, 0x00, 1) } + println('\r100.00% foferk') } -fn write_footer(mut b Bits, repeat int) { +fn write_footer(mut b Bits, repeat i64) { write_msb(mut b, 0x00, 7) flush(mut b) write_u32(mut b, crc32(repeat)) - write_u32(mut b, u32(repeat * 7)) + write_u32(mut b, u32(u64(repeat * 7) & 0xFFFFFFFF)) } // CRC32 -fn crc32(repeat int) u32 { +fn crc32(repeat i64) u32 { mut table := []u32{len: 256} - for i in 0..256 { + for i in 0 .. 256 { mut c := u32(i) - for _ in 0..8 { + for _ in 0 .. 8 { if (c & 1) != 0 { c = 0xEDB88320 ^ (c >> 1) } else { @@ -145,20 +172,35 @@ fn crc32(repeat int) u32 { } mut crc := u32(0xffffffff) - for _ in 0..repeat { - for byte in "foferk ".bytes() { + mut next_log := i64(0) + log_step := if repeat / 10000 == 0 { i64(1) } else { repeat / 10000 } + + for i in 0 .. repeat { + for byte in 'foferk '.bytes() { crc = table[(crc ^ u32(byte)) & 0xFF] ^ (crc >> 8) } + + if i >= next_log { + percent := f64(i) / f64(repeat) * 100.0 + print('\rChecksum: ${percent:6.2f}%') + os.flush() + next_log += log_step + } } + println('\rChecksum: 100.00%') return crc ^ 0xffffffff } fn main() { - repeat := 1_000_000 - mut b := Bits { - bytes: []u8{} + repeat := i64(1_000_000) + + mut file := os.create('foferk.gz') or { panic(err) } + + mut b := Bits{ + file: file + buffer: []u8{cap: 1048576} current: 0 - count: 0 + count: 0 } write_gzip_header(mut b) @@ -167,5 +209,8 @@ fn main() { write_tokens(mut b, repeat) write_footer(mut b, repeat) - os.write_bytes("foferk.gz", b.bytes)! + if b.buffer.len > 0 { + b.file.write(b.buffer) or { panic(err) } + } + file.close() }