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