mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
So far, so good.
This commit is contained in:
@@ -69,6 +69,13 @@ General_Error :: enum {
|
|||||||
Checksum_Failed,
|
Checksum_Failed,
|
||||||
Incompatible_Options,
|
Incompatible_Options,
|
||||||
Unimplemented,
|
Unimplemented,
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Memory errors
|
||||||
|
*/
|
||||||
|
Allocation_Failed,
|
||||||
|
Resize_Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
GZIP_Error :: enum {
|
GZIP_Error :: enum {
|
||||||
|
|||||||
+131
-30
@@ -142,43 +142,121 @@ z_bit_reverse :: #force_inline proc(n: u16, bits: u8) -> (r: u16) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(optimization_mode="speed")
|
||||||
|
grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
|
||||||
|
/*
|
||||||
|
That we get here at all means that we didn't pass an expected output size,
|
||||||
|
or that it was too little.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Double until we reach the maximum allowed.
|
||||||
|
*/
|
||||||
|
new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX);
|
||||||
|
|
||||||
|
resize(buf, new_size);
|
||||||
|
if len(buf) != new_size {
|
||||||
|
/*
|
||||||
|
Resize failed.
|
||||||
|
*/
|
||||||
|
return .Resize_Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: Make these return compress.Error.
|
||||||
|
*/
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
write_byte :: #force_inline proc(z: ^Context, cb: ^Code_Buffer, c: u8) -> (err: io.Error) #no_bounds_check {
|
write_byte :: #force_inline proc(z: ^Context, cb: ^Code_Buffer, c: u8) -> (err: io.Error) #no_bounds_check {
|
||||||
when #config(TRACY_ENABLE, false) { tracy.ZoneN("Write Byte"); }
|
when #config(TRACY_ENABLE, false) { tracy.ZoneN("Write Byte"); }
|
||||||
c := c;
|
c := c;
|
||||||
buf := transmute([]u8)mem.Raw_Slice{data=&c, len=1};
|
|
||||||
when INLINE_ADLER { z.rolling_hash = hash.adler32(buf, z.rolling_hash); }
|
|
||||||
|
|
||||||
_, e := z.output->impl_write(buf);
|
if !z.output_to_stream {
|
||||||
if e != .None {
|
/*
|
||||||
return e;
|
Resize if needed.
|
||||||
|
*/
|
||||||
|
if int(z.bytes_written) + 1 >= len(z.output_buf) {
|
||||||
|
grow_buffer(z.output_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#no_bounds_check {
|
||||||
|
z.output_buf[z.bytes_written] = c;
|
||||||
|
cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
}
|
||||||
|
z.bytes_written += 1;
|
||||||
|
|
||||||
|
when INLINE_ADLER {
|
||||||
|
buf := transmute([]u8)mem.Raw_Slice{data=&c, len=1};
|
||||||
|
z.rolling_hash = hash.adler32(buf, z.rolling_hash);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf := transmute([]u8)mem.Raw_Slice{data=&c, len=1};
|
||||||
|
when INLINE_ADLER {
|
||||||
|
z.rolling_hash = hash.adler32(buf, z.rolling_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
_, e := z.output->impl_write(buf);
|
||||||
|
if e != .None {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#no_bounds_check cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
z.bytes_written += 1;
|
||||||
}
|
}
|
||||||
cb.last[z.bytes_written & cb.window_mask] = c;
|
|
||||||
|
|
||||||
z.bytes_written += 1;
|
|
||||||
return .None;
|
return .None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
repl_byte :: proc(z: ^Context, cb: ^Code_Buffer, count: u16, c: u8) -> (err: io.Error) {
|
repl_byte :: proc(z: ^Context, cb: ^Code_Buffer, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
|
||||||
when #config(TRACY_ENABLE, false) { tracy.ZoneN("Repl Byte"); }
|
when #config(TRACY_ENABLE, false) { tracy.ZoneN("Repl Byte"); }
|
||||||
/*
|
/*
|
||||||
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
|
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
|
||||||
without having to worry about wrapping, so no need for a temp allocation to give to
|
without having to worry about wrapping, so no need for a temp allocation to give to
|
||||||
the output stream, just give it _that_ slice.
|
the output stream, just give it _that_ slice.
|
||||||
*/
|
*/
|
||||||
buf := make([]u8, count, context.temp_allocator);
|
|
||||||
#no_bounds_check for i in 0..<count {
|
|
||||||
buf[i] = c;
|
|
||||||
cb.last[z.bytes_written & cb.window_mask] = c;
|
|
||||||
z.bytes_written += 1;
|
|
||||||
}
|
|
||||||
when INLINE_ADLER { z.rolling_hash = hash.adler32(buf, z.rolling_hash); }
|
|
||||||
|
|
||||||
_, e := z.output->impl_write(buf);
|
if !z.output_to_stream {
|
||||||
if e != .None {
|
/*
|
||||||
return e;
|
Resize if needed.
|
||||||
|
*/
|
||||||
|
if int(z.bytes_written) + int(count) >= len(z.output_buf) {
|
||||||
|
grow_buffer(z.output_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#no_bounds_check {
|
||||||
|
for _ in 0..<count {
|
||||||
|
z.output_buf[z.bytes_written] = c;
|
||||||
|
cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
z.bytes_written += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when INLINE_ADLER {
|
||||||
|
/* TODO(Jeroen): Test */
|
||||||
|
buf := z.output_buf[bytes_written:][:count];
|
||||||
|
z.rolling_hash = hash.adler32(buf, z.rolling_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
buf := make([]u8, count, context.temp_allocator);
|
||||||
|
#no_bounds_check for i in 0..<count {
|
||||||
|
buf[i] = c;
|
||||||
|
cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
z.bytes_written += 1;
|
||||||
|
}
|
||||||
|
when INLINE_ADLER { z.rolling_hash = hash.adler32(buf, z.rolling_hash); }
|
||||||
|
|
||||||
|
_, e := z.output->impl_write(buf);
|
||||||
|
if e != .None {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return .None;
|
return .None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,22 +268,45 @@ repl_bytes :: proc(z: ^Context, cb: ^Code_Buffer, count: u16, distance: u16) ->
|
|||||||
without having to worry about wrapping, so no need for a temp allocation to give to
|
without having to worry about wrapping, so no need for a temp allocation to give to
|
||||||
the output stream, just give it _that_ slice.
|
the output stream, just give it _that_ slice.
|
||||||
*/
|
*/
|
||||||
buf := make([]u8, count, context.temp_allocator);
|
|
||||||
|
|
||||||
offset := z.bytes_written - i64(distance);
|
offset := z.bytes_written - i64(distance);
|
||||||
#no_bounds_check for i in 0..<count {
|
|
||||||
c := cb.last[offset & cb.window_mask];
|
|
||||||
|
|
||||||
cb.last[z.bytes_written & cb.window_mask] = c;
|
if !z.output_to_stream {
|
||||||
buf[i] = c;
|
if int(z.bytes_written) + int(count) >= len(z.output_buf) {
|
||||||
z.bytes_written += 1; offset += 1;
|
grow_buffer(z.output_buf);
|
||||||
}
|
}
|
||||||
when INLINE_ADLER { z.rolling_hash = hash.adler32(buf, z.rolling_hash); }
|
|
||||||
|
|
||||||
_, e := z.output->impl_write(buf);
|
#no_bounds_check {
|
||||||
if e != .None {
|
for _ in 0..<count {
|
||||||
return e;
|
c := cb.last[offset & cb.window_mask];
|
||||||
|
z.output_buf[z.bytes_written] = c;
|
||||||
|
cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
z.bytes_written += 1; offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when INLINE_ADLER {
|
||||||
|
/* TODO(Jeroen): Test */
|
||||||
|
buf := z.output_buf[bytes_written:][:count];
|
||||||
|
z.rolling_hash = hash.adler32(buf, z.rolling_hash);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf := make([]u8, count, context.temp_allocator);
|
||||||
|
#no_bounds_check for i in 0..<count {
|
||||||
|
c := cb.last[offset & cb.window_mask];
|
||||||
|
|
||||||
|
cb.last[z.bytes_written & cb.window_mask] = c;
|
||||||
|
buf[i] = c;
|
||||||
|
z.bytes_written += 1; offset += 1;
|
||||||
|
}
|
||||||
|
when INLINE_ADLER { z.rolling_hash = hash.adler32(buf, z.rolling_hash); }
|
||||||
|
|
||||||
|
_, e := z.output->impl_write(buf);
|
||||||
|
if e != .None {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return .None;
|
return .None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +596,7 @@ inflate_from_stream_raw :: proc(z: ^Context, cb: ^Code_Buffer, expected_output_s
|
|||||||
|
|
||||||
if expected_output_size > -1 && expected_output_size <= compress.COMPRESS_OUTPUT_ALLOCATE_MAX {
|
if expected_output_size > -1 && expected_output_size <= compress.COMPRESS_OUTPUT_ALLOCATE_MAX {
|
||||||
reserve(z.output_buf, expected_output_size);
|
reserve(z.output_buf, expected_output_size);
|
||||||
// resize (z.output_buf, expected_output_size);
|
resize (z.output_buf, expected_output_size);
|
||||||
} else {
|
} else {
|
||||||
reserve(z.output_buf, compress.COMPRESS_OUTPUT_ALLOCATE_MIN);
|
reserve(z.output_buf, compress.COMPRESS_OUTPUT_ALLOCATE_MIN);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user