-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
999f632
commit cc41e55
Showing
14 changed files
with
9,018 additions
and
8,449 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import std::shift_args | ||
import std::fs | ||
import std::huffman | ||
|
||
enum Mode { | ||
Compress | ||
Decompress | ||
None | ||
} | ||
|
||
def usage(code: i32, full: bool) { | ||
println("Usage:") | ||
println(" ./huffman <-c|-d> -i <path> -o <path>") | ||
if not full then std::exit(code) | ||
|
||
println("--------------------------------------------------------") | ||
println("Compile Options:") | ||
println(" -i path Input path") | ||
println(" -o path Output path") | ||
println(" -c Compress") | ||
println(" -d Decompress") | ||
println(" -h Display this information") | ||
std::exit(code) | ||
} | ||
|
||
let mode: Mode = None | ||
let input: str = "/dev/stdin" | ||
let output: str = "/dev/stdout" | ||
|
||
|
||
def parse_args(argc: &i32, argv: &&str) { | ||
while *argc > 0 { | ||
let arg = shift_args(argc, argv) | ||
match arg { | ||
"-h" | "--help" => usage(code: 0, true) | ||
"-i" | "--input" => input = shift_args(argc, argv) | ||
"-o" | "--output" => output = shift_args(argc, argv) | ||
"-c" | "--compress" => mode = Compress | ||
"-d" | "--decompress" => mode = Decompress | ||
else => { | ||
println("Unknown option/argument: '%s'", arg) | ||
usage(code: 1, true) | ||
} | ||
} | ||
} | ||
|
||
if mode == None { | ||
println("Mode was not selected. Please choose -c or -d") | ||
usage(code: 1, true) | ||
} | ||
} | ||
|
||
def main(argc: i32, argv: &str) { | ||
shift_args(&argc, &argv) | ||
parse_args(&argc, &argv) | ||
let file = fs::read_file_inc(input) | ||
let res = match mode { | ||
Compress => huffman::compress(&file) | ||
Decompress => huffman::decompress(&file) | ||
None => std::panic("unreachable") | ||
} | ||
fs::write_file(output, res) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//! Wrapper over {{Buffer}} and {{SV}} that let you read/write one bit at a time. | ||
import std::buffer::{ Buffer } | ||
import std::sv::{ SV } | ||
|
||
struct BitWriter { | ||
buffer: &Buffer | ||
byte: u8 | ||
bit: u8 | ||
} | ||
|
||
def BitWriter::make(buffer: &Buffer): BitWriter { | ||
return BitWriter( | ||
buffer: buffer, | ||
byte: 0, | ||
bit: 0 | ||
) | ||
} | ||
|
||
def BitWriter::write_bit(&this, bit: u8) { | ||
if bit != 0 { | ||
.byte = .byte | (1u8 << .bit) | ||
} else { | ||
.byte = .byte & ~(1u8 << .bit) | ||
} | ||
if ++.bit == 8 { | ||
.buffer.write_u8(.byte) | ||
.byte = 0 | ||
.bit = 0 | ||
} | ||
} | ||
|
||
def BitWriter::write_u8(&this, byte: u8) { | ||
for let i = 0u8; i < 8; i++ { | ||
.write_bit((byte >> i) & 1) | ||
} | ||
} | ||
|
||
def BitWriter::finish(&this) { | ||
if .bit != 0 { | ||
.buffer.write_u8(.byte) | ||
} | ||
} | ||
|
||
|
||
struct BitReader { | ||
data: &u8 | ||
num_bits: u32 // Maximum number of bits to read | ||
idx: u32 | ||
} | ||
|
||
def BitReader::from_data(data: &u8, num_bits: u32): BitReader { | ||
return BitReader( | ||
data: data, | ||
num_bits: num_bits, | ||
idx: 0 | ||
) | ||
} | ||
|
||
def BitReader::from_sv(sv: SV, num_bits: u32 = 0): BitReader { | ||
if num_bits == 0 { | ||
num_bits = sv.len * 8 | ||
} | ||
return BitReader::from_data(sv.data as &u8, num_bits) | ||
} | ||
|
||
def BitReader::read_bit(&this): u8 { | ||
if .idx >= .num_bits { | ||
return 0 | ||
} | ||
let byte = .data[.idx / 8] | ||
let bit_offset = (.idx % 8) as u8 | ||
let bit = (byte >> bit_offset) & 1 | ||
.idx += 1 | ||
return bit | ||
} | ||
|
||
def BitReader::read_u8(&this): u8 { | ||
let byte: u8 = 0 | ||
for let i = 0u8; i < 8; i++ { | ||
byte = byte | (.read_bit() << i) | ||
} | ||
return byte | ||
} | ||
|
||
def BitReader::has_bits(&this): bool => .idx < .num_bits | ||
|
||
// Iterator methods | ||
def BitReader::has_value(&this): bool => .idx < .num_bits | ||
def BitReader::cur(&this): u8 => .data[.idx / 8] >> (.idx % 8) as u8 & 1 | ||
def BitReader::next(&this) => .idx += 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.