annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 namespace bitreader_helper {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 inline static size_t extract_bit(const uint8_t * p_stream,size_t p_offset) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 return (p_stream[p_offset>>3] >> (7-(p_offset&7)))&1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 inline static size_t extract_int(const uint8_t * p_stream,size_t p_base,size_t p_width) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 size_t ret = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 size_t offset = p_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 for(size_t bit=0;bit<p_width;bit++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 ret <<= 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 ret |= extract_bit(p_stream,offset++);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 inline static void write_bit( uint8_t * p_stream, size_t p_offset, size_t bit ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 size_t bshift = 7 - (p_offset&7);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 size_t mask = (size_t)1 << bshift;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 uint8_t & b = p_stream[p_offset>>3];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 b = (b & ~mask) | ((bit&1) << bshift);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 inline static void write_int( uint8_t * p_stream, size_t p_base, size_t p_width, size_t p_value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 size_t offset = p_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 size_t val = p_value;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 for( size_t bit = 0; bit < p_width; ++ bit ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 write_bit( p_stream, offset++, val >> (p_width - bit - 1));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 class bitreader
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 inline bitreader(const t_uint8 * p_ptr,t_size p_base)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 : m_ptr(p_ptr), m_bitptr(p_base)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 inline void skip(t_size p_bits)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 m_bitptr += p_bits;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 template<typename t_ret>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 t_ret peek_t(t_size p_bits) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 size_t ptr = m_bitptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 t_ret ret = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 for(t_size bit=0;bit<p_bits;bit++)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 ret <<= 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 ret |= (m_ptr[ptr >>3] >> (7-(ptr &7)))&1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 ptr++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 template<typename t_ret>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 t_ret read_t(t_size p_bits) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 t_ret ret = peek_t<t_ret>(p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 skip(p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 size_t peek(size_t bits) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 return peek_t<size_t>(bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 t_size read(t_size p_bits) {return read_t<t_size>(p_bits);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 inline t_size get_bitptr() const {return m_bitptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 inline bool read_bit() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 bool state = ( (m_ptr[m_bitptr>>3] >> (7-(m_bitptr&7)))&1 ) != 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 m_bitptr++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 return state;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 const t_uint8 * m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 t_size m_bitptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 class bitreader_fromfile
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 inline bitreader_fromfile(service_ptr_t<file> const& p_file) : m_file(p_file), m_buffer_ptr(0) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 t_size read(t_size p_bits,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 t_size ret = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 for(t_size bit=0;bit<p_bits;bit++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 if (m_buffer_ptr == 0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 m_file->read_object(&m_buffer,1,p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 ret <<= 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 ret |= (m_buffer >> (7-m_buffer_ptr))&1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 m_buffer_ptr = (m_buffer_ptr+1) & 7;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 void skip(t_size p_bits,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 for(t_size bit=0;bit<p_bits;bit++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 if (m_buffer_ptr == 0) m_file->read_object(&m_buffer,1,p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 m_buffer_ptr = (m_buffer_ptr+1) & 7;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 inline void byte_align() {m_buffer_ptr = 0;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 service_ptr_t<file> m_file;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 t_size m_buffer_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 t_uint8 m_buffer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 class bitreader_limited
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 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) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 inline t_size get_bitptr() const {return m_reader.get_bitptr();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 inline t_size get_remaining() const {return m_remaining;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 inline void skip(t_size p_bits) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 if (p_bits > m_remaining) throw exception_io_data_truncation();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 m_remaining -= p_bits;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 m_reader.skip(p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 size_t peek(size_t bits) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 if (bits > m_remaining) throw exception_io_data_truncation();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 return m_reader.peek(bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 t_size read(t_size p_bits)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 if (p_bits > m_remaining) throw exception_io_data_truncation();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 m_remaining -= p_bits;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 return m_reader.read(p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 bitreader m_reader;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 t_size m_remaining;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 inline static t_size extract_bits(const t_uint8 * p_buffer,t_size p_base,t_size p_count) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 return bitreader(p_buffer,p_base).read(p_count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 }