core/compress
compress
Types
8Context_Memory_Input
Context_Memory_Input :: struct #packed {
input_data: []u8,
output: ^bytes.Buffer,
bytes_written: i64,
code_buffer: u64,
num_bits: u64,
// If we know the data size, we can optimize the reads and writes.
size_packed: i64,
size_unpacked: i64,
}SourceGeneral I/O context for ZLIB, LZW, etc.
Context_Stream_Input
Context_Stream_Input :: struct #packed {
input_data: []u8,
input: io.Stream,
output: ^bytes.Buffer,
bytes_written: i64,
code_buffer: u64,
num_bits: u64,
// If we know the data size, we can optimize the reads and writes.
size_packed: i64,
size_unpacked: i64,
// Flags:
// `input_fully_in_memory`
// true = This tells us we read input from `input_data` exclusively. [] = EOF.
// false = Try to refill `input_data` from the `input` stream.
input_fully_in_memory: b8,
padding: [1]u8,
}SourceDeflate_Error
Deflate_Error :: enum int {
None = 0,
Huffman_Bad_Sizes = 1,
Huffman_Bad_Code_Lengths = 2,
Inflate_Error = 3,
Bad_Distance = 4,
Bad_Huffman_Code = 5,
Len_Nlen_Mismatch = 6,
BType_3 = 7,
}SourceError
Error :: union {
General_Error,
Deflate_Error,
ZLIB_Error,
GZIP_Error,
ZIP_Error,
runtime.Allocator_Error,
}SourceGZIP_Error
GZIP_Error :: enum int {
None = 0,
Invalid_GZIP_Signature = 1,
Reserved_Flag_Set = 2,
Invalid_Extra_Data = 3,
Original_Name_Too_Long = 4,
Comment_Too_Long = 5,
Payload_Length_Invalid = 6,
Payload_CRC_Invalid = 7,
// GZIP's payload can be a maximum of max(u32le), or 4 GiB.
// If you tell it you expect it to contain more, that's obviously an error.
Payload_Size_Exceeds_Max_Payload = 8,
// For buffered instead of streamed output, the payload size can't exceed
// the max set by the `COMPRESS_OUTPUT_ALLOCATE_MAX` switch in compress/common.odin.
//
// You can tweak this setting using `-define:COMPRESS_OUTPUT_ALLOCATE_MAX=size_in_bytes`
Output_Exceeds_COMPRESS_OUTPUT_ALLOCATE_MAX = 9,
}SourceGeneral_Error
General_Error :: enum int {
None = 0,
File_Not_Found = 1,
Cannot_Open_File = 2,
File_Too_Short = 3,
Stream_Too_Short = 4,
Output_Too_Short = 5,
Unknown_Compression_Method = 6,
Checksum_Failed = 7,
Incompatible_Options = 8,
Unimplemented = 9,
// Memory errors
Allocation_Failed = 10,
Resize_Failed = 11,
}SourceZIP_Error
ZIP_Error :: enum int {
None = 0,
Invalid_ZIP_File_Signature = 1,
Unexpected_Signature = 2,
Insert_Next_Disk = 3,
Expected_End_of_Central_Directory_Record = 4,
}SourceZLIB_Error
ZLIB_Error :: enum int {
None = 0,
Unsupported_Window_Size = 1,
FDICT_Unsupported = 2,
Unsupported_Compression_Level = 3,
Code_Buffer_Malformed = 4,
}SourceConstants
1COMPRESS_OUTPUT_ALLOCATE_MIN
COMPRESS_OUTPUT_ALLOCATE_MIN :: int = int(#config(COMPRESS_OUTPUT_ALLOCATE_MIN, 1 << 20))SourceWhen a decompression routine doesn't stream its output, but writes to a buffer, we pre-allocate an output buffer to speed up decompression. The default is 1 MiB.
Procedures
27consume_bits_lsb_from_memory
consume_bits_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: u8)Sourceconsume_bits_lsb_from_stream
consume_bits_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: u8)Sourcediscard_to_next_byte_lsb_from_memory
discard_to_next_byte_lsb_from_memory :: proc(z: ^Context_Memory_Input)Sourcediscard_to_next_byte_lsb_from_stream
discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input)Sourceinput_size_from_memory
input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Error)SourceTODO: The stream versions should really only check if a certain method is available once, perhaps even during setup.
Bit and byte readers may be merged so that reading bytes will grab them from the bit buffer first.
This simplifies end-of-stream handling where bits may be left in the bit buffer.input_size_from_stream
input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error)Sourcepeek_back_byte
peek_back_byte :: proc(z: ^C, offset: i64) -> (res: u8, err: io.Error)SourceSliding window read back
peek_bits_lsb_from_memory
peek_bits_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: u8) -> (u32)Sourcepeek_bits_lsb_from_stream
peek_bits_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: u8) -> (u32)Sourcepeek_bits_no_refill_lsb_from_memory
peek_bits_no_refill_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: u8) -> (u32)Sourcepeek_bits_no_refill_lsb_from_stream
peek_bits_no_refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: u8) -> (u32)Sourcepeek_data_at_offset_from_memory
peek_data_at_offset_from_memory :: proc(z: ^Context_Memory_Input, T: typeid, offset: int) -> (res: T, err: io.Error)Sourcepeek_data_at_offset_from_stream
peek_data_at_offset_from_stream :: proc(z: ^Context_Stream_Input, T: typeid, offset: int) -> (res: T, err: io.Error)Sourcepeek_data_from_memory
peek_data_from_memory :: proc(z: ^Context_Memory_Input, T: typeid) -> (res: T, err: io.Error)Sourcepeek_data_from_stream
peek_data_from_stream :: proc(z: ^Context_Stream_Input, T: typeid) -> (res: T, err: io.Error)Sourceread_bits_lsb_from_memory
read_bits_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: u8) -> (u32)Sourceread_bits_lsb_from_stream
read_bits_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: u8) -> (u32)Sourceread_bits_no_refill_lsb_from_memory
read_bits_no_refill_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: u8) -> (u32)Sourceread_bits_no_refill_lsb_from_stream
read_bits_no_refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: u8) -> (u32)Sourceread_data
read_data :: proc(z: ^C, T: typeid) -> (res: T, err: io.Error)Sourceread_slice_from_memory
read_slice_from_memory :: proc(z: ^Context_Memory_Input, size: int) -> (res: []u8, err: io.Error)Sourceread_slice_from_stream
read_slice_from_stream :: proc(z: ^Context_Stream_Input, size: int) -> (res: []u8, err: io.Error)Sourceread_u8_from_memory
read_u8_from_memory :: proc(z: ^Context_Memory_Input) -> (res: u8, err: io.Error)Sourceread_u8_from_stream
read_u8_from_stream :: proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error)Sourceread_u8_prefer_code_buffer_lsb
read_u8_prefer_code_buffer_lsb :: proc(z: ^C) -> (res: u8, err: io.Error)SourceYou would typically only use this at the end of Inflate, to drain bits from the code buffer preferentially.
refill_lsb_from_memory
refill_lsb_from_memory :: proc(z: ^Context_Memory_Input, width: i8 = i8(48))SourceGeneralized bit reader LSB
refill_lsb_from_stream
refill_lsb_from_stream :: proc(z: ^Context_Stream_Input, width: i8 = i8(24))SourceGeneralized bit reader LSB
Procedure Groups
11consume_bits_lsb
consume_bits_lsb :: proc{consume_bits_lsb_from_memory, consume_bits_lsb_from_stream}Sourcediscard_to_next_byte_lsb
discard_to_next_byte_lsb :: proc{discard_to_next_byte_lsb_from_memory, discard_to_next_byte_lsb_from_stream}Sourceinput_size
input_size :: proc{input_size_from_memory, input_size_from_stream}Sourcepeek_bits_lsb
peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}Sourcepeek_bits_no_refill_lsb
peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}Sourcepeek_data
peek_data :: proc{peek_data_from_memory, peek_data_from_stream, peek_data_at_offset_from_memory, peek_data_at_offset_from_stream}Sourceread_bits_lsb
read_bits_lsb :: proc{read_bits_lsb_from_memory, read_bits_lsb_from_stream}Sourceread_bits_no_refill_lsb
read_bits_no_refill_lsb :: proc{read_bits_no_refill_lsb_from_memory, read_bits_no_refill_lsb_from_stream}Sourceread_slice
read_slice :: proc{read_slice_from_memory, read_slice_from_stream}Sourceread_u8
read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}Sourcerefill_lsb
refill_lsb :: proc{refill_lsb_from_memory, refill_lsb_from_stream}Source