Files

96 lines
2.1 KiB
Odin
Raw Permalink Normal View History

2024-06-11 22:57:04 +02:00
package flac
import "core:io"
/* Basic byte and bit reader.
2024-06-11 22:57:04 +02:00
Uses core:bytes reader under the hood with a few useful procedures for reading structs and other types.
*/
2026-09-11 15:12:53 +02:00
// Public because load_from_file hands one back; everything else in this file
// stays package-private.
2024-06-11 22:57:04 +02:00
Reader :: struct {
2024-06-19 04:08:54 +02:00
using r: io.Stream,
// Temporary read buffer.
buf: [8]u8,
// Between 0 and 7 buffered bits since previous read operations.
x: u8,
// The number of buffered bits in x.
n: uint,
2024-06-11 22:57:04 +02:00
}
2024-06-19 04:08:54 +02:00
read_slice :: #force_inline proc(r: ^Reader, buf: []u8) -> io.Error {
io.read_full(r^, buf) or_return
2024-06-11 22:57:04 +02:00
2024-06-19 04:08:54 +02:00
return nil
2024-06-11 22:57:04 +02:00
}
read_data :: #force_inline proc(r: ^Reader, $T: typeid) -> (res: T, err: io.Error) {
2024-09-24 03:50:34 +02:00
// b is safe to return here because the proc is always inlined.
2024-06-19 04:08:54 +02:00
b: [size_of(T)]byte
read_slice(r, b[:]) or_return
2024-06-11 22:57:04 +02:00
return (^T)(&b[0])^, nil
}
2024-06-19 04:08:54 +02:00
// Read reads and returns the next n bits, at most 64. It buffers bits up to the
// next byte boundary.
// Borrowed from https://github.com/mewkiz/flac
2026-09-11 15:12:53 +02:00
@(private)
2024-06-19 04:08:54 +02:00
read_bits :: proc(r: ^Reader, n: uint) -> (res: u64, err: io.Error) #no_bounds_check {
if n == 0 {
return 0, nil
2024-06-11 22:57:04 +02:00
}
2024-06-19 04:08:54 +02:00
n := n
// Read buffered bits.
if r.n > 0 {
switch {
case r.n == n:
r.n = 0
return u64(r.x), nil
case r.n > n:
r.n -= n
mask := ~u8(0) << r.n
res = u64(r.x&mask) >> r.n
r.x &~= mask
return res, nil
}
2024-06-19 04:08:54 +02:00
n -= r.n
res = u64(r.x)
r.n = 0
}
2024-06-14 03:58:36 +02:00
2024-06-19 04:08:54 +02:00
// Fill the temporary buffer.
bytes := n / 8
bits := n % 8
if bits > 0 {
bytes += 1
}
2024-06-19 04:08:54 +02:00
io.read_full(r, r.buf[:bytes]) or_return
2024-06-14 03:58:36 +02:00
2024-06-19 04:08:54 +02:00
// Read bits from the temporary buffer.
for b in r.buf[:bytes-1] {
res <<= 8
res |= u64(b)
}
2024-06-19 04:08:54 +02:00
b := r.buf[bytes-1]
if bits > 0 {
res <<= bits
r.n = 8 - bits
mask := ~u8(0) << r.n
res |= u64(b&mask) >> r.n
r.x = b & ~mask
} else {
res <<= 8
res |= u64(b)
}
2024-06-14 03:58:36 +02:00
return res, nil
2024-06-11 22:57:04 +02:00
}
2026-09-11 15:12:53 +02:00
@(private)
2024-06-19 04:08:54 +02:00
align_to_byte :: proc(r: ^Reader) {
r.x = 0
r.n = 0
2024-06-11 22:57:04 +02:00
}