diff foosdk/sdk/foobar2000/helpers/bitreader_helper.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/helpers/bitreader_helper.h	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,154 @@
+#pragma once
+
+namespace bitreader_helper {
+
+	inline static size_t extract_bit(const uint8_t * p_stream,size_t p_offset) {
+		return (p_stream[p_offset>>3] >> (7-(p_offset&7)))&1;
+	}
+
+	inline static size_t extract_int(const uint8_t * p_stream,size_t p_base,size_t p_width) {
+		size_t ret = 0;
+		size_t offset = p_base;
+		for(size_t bit=0;bit<p_width;bit++) {
+			ret <<= 1;
+			ret |= extract_bit(p_stream,offset++);
+		}
+		return ret;
+	}
+    inline static void write_bit( uint8_t * p_stream, size_t p_offset, size_t bit ) {
+        size_t bshift = 7 - (p_offset&7);
+        size_t mask = (size_t)1 << bshift;
+        uint8_t & b = p_stream[p_offset>>3];
+        b = (b & ~mask) | ((bit&1) << bshift);
+    }
+    inline static void write_int( uint8_t * p_stream, size_t p_base, size_t p_width, size_t p_value) {
+        size_t offset = p_base;
+        size_t val = p_value;
+        for( size_t bit = 0; bit < p_width; ++ bit ) {
+            write_bit( p_stream, offset++, val >> (p_width - bit - 1));
+        }
+    }
+
+class bitreader
+{
+public:
+	inline bitreader(const t_uint8 * p_ptr,t_size p_base)
+		: m_ptr(p_ptr), m_bitptr(p_base)
+	{
+	}
+
+	inline void skip(t_size p_bits)
+	{
+		m_bitptr += p_bits;
+	}
+
+	
+	template<typename t_ret>
+	t_ret peek_t(t_size p_bits) const {
+		size_t ptr = m_bitptr;
+		t_ret ret = 0;
+		for(t_size bit=0;bit<p_bits;bit++)
+		{
+			ret <<= 1;
+			ret |= (m_ptr[ptr >>3] >> (7-(ptr &7)))&1;
+			ptr++;
+		}
+		return ret;
+	}
+
+	template<typename t_ret>
+	t_ret read_t(t_size p_bits) {
+		t_ret ret = peek_t<t_ret>(p_bits);
+		skip(p_bits);
+		return ret;
+	}
+
+	size_t peek(size_t bits) const {
+		return peek_t<size_t>(bits);
+	}
+
+	t_size read(t_size p_bits) {return read_t<t_size>(p_bits);}
+
+	inline t_size get_bitptr() const {return m_bitptr;}
+
+	inline bool read_bit() {
+		bool state = ( (m_ptr[m_bitptr>>3] >> (7-(m_bitptr&7)))&1 ) != 0;
+		m_bitptr++;
+		return state;
+	}
+
+private:
+
+	const t_uint8 * m_ptr;
+	t_size m_bitptr;
+};
+
+class bitreader_fromfile
+{
+public:
+	inline bitreader_fromfile(service_ptr_t<file> const& p_file) : m_file(p_file), m_buffer_ptr(0) {}
+	
+	t_size read(t_size p_bits,abort_callback & p_abort) {
+		t_size ret = 0;
+		for(t_size bit=0;bit<p_bits;bit++) {
+			if (m_buffer_ptr == 0)
+				m_file->read_object(&m_buffer,1,p_abort);
+
+			ret <<= 1;
+			ret |= (m_buffer >> (7-m_buffer_ptr))&1;
+			m_buffer_ptr = (m_buffer_ptr+1) & 7;
+		}
+		return ret;
+	}
+
+	void skip(t_size p_bits,abort_callback & p_abort) {
+		for(t_size bit=0;bit<p_bits;bit++) {
+			if (m_buffer_ptr == 0) m_file->read_object(&m_buffer,1,p_abort);
+			m_buffer_ptr = (m_buffer_ptr+1) & 7;
+		}
+	}
+
+	inline void byte_align() {m_buffer_ptr = 0;}
+
+private:
+	service_ptr_t<file> m_file;
+	t_size m_buffer_ptr;
+	t_uint8 m_buffer;
+};
+
+class bitreader_limited
+{
+public:
+	inline bitreader_limited(const t_uint8 * p_ptr,t_size p_base,t_size p_remaining) : m_reader(p_ptr,p_base), m_remaining(p_remaining) {}
+
+	inline t_size get_bitptr() const {return m_reader.get_bitptr();}
+
+	inline t_size get_remaining() const {return m_remaining;}
+
+	inline void skip(t_size p_bits) {
+		if (p_bits > m_remaining) throw exception_io_data_truncation();
+		m_remaining -= p_bits;
+		m_reader.skip(p_bits);
+	}
+
+	size_t peek(size_t bits) {
+		if (bits > m_remaining) throw exception_io_data_truncation();
+		return m_reader.peek(bits);
+	}
+	t_size read(t_size p_bits)
+	{
+		if (p_bits > m_remaining) throw exception_io_data_truncation();
+		m_remaining -= p_bits;
+		return m_reader.read(p_bits);
+	}
+
+private:
+	bitreader m_reader;
+	t_size m_remaining;
+};
+
+inline static t_size extract_bits(const t_uint8 * p_buffer,t_size p_base,t_size p_count) {
+	return bitreader(p_buffer,p_base).read(p_count);
+}
+
+}