Mstdlib-1.24.0
m_bit_buf.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2017 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_BIT_BUF_H__
25#define __M_BIT_BUF_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_buf.h>
32
33/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
34
35__BEGIN_DECLS
36
37/*! \addtogroup m_bit_buf Bitwise Buffered Data Builder
38 * \ingroup mstdlib_base
39 *
40 * Allows for buffered writing of data that's organized per-bit, instead of per-byte.
41 *
42 * Also allows for changing bits that were previously added to the buffer (see M_bit_buf_update_bit()). This
43 * allows for random-access setting of individual bits. For example, if you're generating a bit-level image,
44 * you can fill the buffer with zero bits, and then set individual bits afterwards in whatever order you wish.
45 *
46 * When you're done adding data, the contents of the buffer can be output as a continuous byte-array, either
47 * raw as an (M_uint8 *), or inside a regular per-byte M_buf_t.
48 *
49 * Example (creating a buffer, adding data, finishing the buffer):
50 *
51 * \code{.c}
52 * M_bit_buf_t *bbuf;
53 * M_uint8 *out;
54 * size_t out_nbytes;
55 *
56 * bbuf = M_bit_buf_create();
57 * M_bit_buf_add_bit(bbuf, 1);
58 * M_bit_buf_add(bbuf, 0xA2C4, 14); // adds least-significant 14 bits of 0xA2C4
59 * M_bit_buf_add_bitstr(bbuf, "100010000"); // adds 9 bits from binary-ASCII
60 *
61 * out = M_bit_buf_finish(bbuf, &out_nbytes);
62 *
63 * // out now points to a byte buffer containing 3 bytes. Now can output to disk, do further processing, etc.
64 *
65 * M_free(out);
66 * \endcode
67 *
68 * @{
69 */
70
71struct M_bit_buf;
72typedef struct M_bit_buf M_bit_buf_t;
73
74/*! Enumeration for byte-alignment padding mode for M_bit_buf_add().*/
75typedef enum {
76 M_BIT_BUF_PAD_NONE = 0, /*!< Don't add any padding. */
77 M_BIT_BUF_PAD_BEFORE, /*!< Pad with zero bits before new value, so that bit stream after add is byte-aligned */
78 M_BIT_BUF_PAD_AFTER /*!< Pad with zero bits after new value, so that bit stream after add is byte-aligned */
80
81
82/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
83
84/*! Create a new bit buffer.
85 *
86 * \return allocated buffer.
87 *
88 * \see M_bit_buf_destroy
89 * \see M_bit_buf_finish
90 * \see M_bit_buf_finish_buf
91 */
92M_API M_bit_buf_t *M_bit_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC;
93
94
95/*! Free a bit buffer, discarding its data.
96 *
97 * \param[in] bbuf bit buffer to destroy
98 */
99M_API void M_bit_buf_destroy(M_bit_buf_t *bbuf) M_FREE(1);
100
101
102/*! Free a buffer, saving its data.
103 *
104 * The caller is responsible for freeing the data.
105 *
106 * \param[in] bbuf Bit buffer
107 * \param[out] nbytes Data length (in bytes)
108 * \return The buffered data.
109 *
110 * \see M_free
111 */
112M_API M_uint8 *M_bit_buf_finish(M_bit_buf_t *bbuf, size_t *nbytes) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC;
113
114
115/*! Free a buffer, saving its data in a per-byte buffer.
116 *
117 * The caller is responsible for freeing the data.
118 *
119 * \param[in] bbuf Bit buffer
120 *
121 * \return The buffered data.
122 *
123 * \see M_free
124 */
125M_API M_buf_t *M_bit_buf_finish_buf(M_bit_buf_t *bbuf) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC;
126
127
128/*! Return the length of the data held by a buffer, in bits.
129 *
130 * \param[in] bbuf Bit buffer
131 * \return Data length (in bits)
132 */
133M_API size_t M_bit_buf_len(const M_bit_buf_t *bbuf);
134
135
136/*! Return the length of the data held by a buffer, in bytes.
137 *
138 * Partial bytes will be rounded up (i.e., 9 bits stored == 2 bytes).
139 *
140 * \param[in] bbuf Bit buffer
141 * \return Data length (in bytes)
142 */
143M_API size_t M_bit_buf_len_bytes(const M_bit_buf_t *bbuf);
144
145
146/*! Return pointer to internal buffer data.
147 *
148 * The internal data is stored as an array of bytes. The first bit in the buffer is always
149 * guaranteed to be the highest bit in the first byte, second bit in the buffer is the next
150 * highest bit, and so on. The implementation guarantees this will always be the case,
151 * regardless of what operations you may have done on the bit buffer.
152 *
153 * \warning
154 * The returned pointer may be invalidated when you add data to the buffer. For safety,
155 * it should be used immediately after you call M_bit_buf_peek(), and then discarded.
156 *
157 * \param[in] bbuf Bit buffer
158 * \return pointer to current internal buffer data
159 */
160M_API const M_uint8 *M_bit_buf_peek(const M_bit_buf_t *bbuf);
161
162
163/*! Truncate the length of the data to the specified size (in bits).
164 *
165 * Removes data from the end of the buffer.
166 *
167 * \param[in,out] bbuf Bit buffer
168 * \param[in] len_bits Length (in bits) to truncate buffer to
169 */
170M_API void M_bit_buf_truncate(M_bit_buf_t *bbuf, size_t len_bits);
171
172
173/*! Add a number of repetitions of the same bit to the buffer.
174 *
175 * \param[in,out] bbuf Bit buffer
176 * \param[in] bit 1 (to add a set bit) or 0 (to add an unset bit)
177 * \param[in] len_bits Number of bits to add
178 */
179M_API void M_bit_buf_fill(M_bit_buf_t *bbuf, M_uint8 bit, size_t len_bits);
180
181
182/*! Add the given bit to the buffer.
183 *
184 * \param[in,out] bbuf Bit buffer
185 * \param[in] bit 1 (to add a set bit) or 0 (to add an unset bit)
186 */
187M_API void M_bit_buf_add_bit(M_bit_buf_t *bbuf, M_uint8 bit);
188
189
190/*! Add given bit at given location in buffer, filling in gaps as necessary.
191 *
192 * If the requested bit_idx has already been set in the buffer, this function
193 * will simply update it to the requested value.
194 *
195 * If the requested bit_idx hasn't already been set, the size of the buffer will
196 * be increased up to the requested bit_idx, and then that bit will be set. Any
197 * new bits that had to be added before the requested bit_idx will be set to
198 * the value of 'fill_bit'.
199 *
200 * If you only want to update bits that have already been set, use M_bit_buf_update_bit().
201 *
202 * Usage example:
203 * \code{.c}
204 * M_bit_buf_t *bbuf = M_bit_buf_create();
205 * M_bit_buf_add_bitstr(bbuf, "101"); // bit buf contains "101"
206 * M_bit_buf_set_bit(bbuf, 1, 5, 0); // bit buf now contains "101001" (idx 3 and 4 get 'fill_bit', 5 gets 'bit')
207 * \endcode
208 *
209 * \see M_bit_buf_update_bit
210 *
211 */
212M_API void M_bit_buf_set_bit(M_bit_buf_t *bbuf, M_uint8 bit, size_t bit_idx, M_uint8 fill_bit);
213
214
215/*! Change one of the bits already in the buffer.
216 *
217 * This function is guaranteed to never change the length of the bit stream - it will only update bits
218 * that are already present. If you want to add a bit past the end of the stream, and automatically
219 * fill any bits between the old end of the stream and the new bit, use M_bit_buf_set_bit().
220 *
221 * \see M_bit_buf_set_bit
222 *
223 * \param[in] bbuf Bit buffer
224 * \param[in] bit_idx index of bit to change, must be less than M_bit_buf_len()
225 * \param[in] bit 1 to set the bit, 0 to unset it
226 * \return M_TRUE on success, M_FALSE if requested bit index too large (not in buffer yet)
227 */
228M_API M_bool M_bit_buf_update_bit(M_bit_buf_t *bbuf, size_t bit_idx, M_uint8 bit);
229
230
231/*! Add bits from the given variable-length chunk of data.
232 *
233 * \param[in,out] bbuf Bit buffer
234 * \param[in] bytes data to add
235 * \param[in] nbits number of bits to add from the given data
236 */
237M_API void M_bit_buf_add_bytes(M_bit_buf_t *bbuf, const void *bytes, size_t nbits);
238
239
240/*! Add bits from a given integer to the buffer.
241 *
242 * Note that the bit region being read is assumed to be justified against the least-significant end of the
243 * integer, though the bits within that region are read from most-significant to least-significant.
244 *
245 * For example, if bits == 0x8B == (10001011)b, and nbits == 4, the bits "1011" will be added to the buffer.
246 *
247 * \param[in,out] bbuf Bit buffer
248 * \param[in] bits Value to draw bits from
249 * \param[in] nbits Number of bits to use (counted from least-significant end, right-to-left)
250 * \param[in] pad Should any bits be added to force the result to end on a byte-boundary
251 */
252M_API void M_bit_buf_add(M_bit_buf_t *bbuf, M_uint64 bits, size_t nbits, M_bit_buf_pad_t pad);
253
254
255/*! Add bits from a given binary-ascii string to the buffer.
256 *
257 * A binary-ascii string is a list of 1 and 0 characters (e.g., "100010").
258 *
259 * Any whitespace in the string will be silently ignored. So, " 1000 1 0" will add the same data as "100010".
260 *
261 * \param[in,out] bbuf Bit buffer
262 * \param[in] bitstr String to draw bits from
263 * \param[in] pad Should any bits be added to force the result to end on a byte-boundary
264 *
265 * \return M_FALSE on error (given bitstr had characters other than '0', '1', or whitespace).
266 */
267M_API M_bool M_bit_buf_add_bitstr(M_bit_buf_t *bbuf, const char *bitstr, M_bit_buf_pad_t pad);
268
269
270/*! Provide hint to buffer about how many bits we're going to add.
271 *
272 * If you know ahead of time how many bits are going to get added to the buffer, you can
273 * use this function to grow the buffer all at once ahead of time, instead of on-demand
274 * as the buffer runs out of internal space.
275 *
276 * This is provided purely as a performance hint.
277 *
278 * \param bbuf Bit buffer
279 * \param nbits Number of bits that we expect to add in the future
280 */
281M_API void M_bit_buf_reserve(M_bit_buf_t *bbuf, size_t nbits);
282
283/*! @} */
284
285__END_DECLS
286
287#endif /* __M_BIT_BUF_H__ */
void M_bit_buf_truncate(M_bit_buf_t *bbuf, size_t len_bits)
void M_bit_buf_set_bit(M_bit_buf_t *bbuf, M_uint8 bit, size_t bit_idx, M_uint8 fill_bit)
M_bit_buf_pad_t
Definition: m_bit_buf.h:75
size_t M_bit_buf_len(const M_bit_buf_t *bbuf)
struct M_bit_buf M_bit_buf_t
Definition: m_bit_buf.h:72
M_bool M_bit_buf_add_bitstr(M_bit_buf_t *bbuf, const char *bitstr, M_bit_buf_pad_t pad)
M_bool M_bit_buf_update_bit(M_bit_buf_t *bbuf, size_t bit_idx, M_uint8 bit)
void M_bit_buf_add(M_bit_buf_t *bbuf, M_uint64 bits, size_t nbits, M_bit_buf_pad_t pad)
void M_bit_buf_fill(M_bit_buf_t *bbuf, M_uint8 bit, size_t len_bits)
M_bit_buf_t * M_bit_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC
M_buf_t * M_bit_buf_finish_buf(M_bit_buf_t *bbuf) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC
void M_bit_buf_reserve(M_bit_buf_t *bbuf, size_t nbits)
void M_bit_buf_add_bytes(M_bit_buf_t *bbuf, const void *bytes, size_t nbits)
void M_bit_buf_destroy(M_bit_buf_t *bbuf) M_FREE(1)
size_t M_bit_buf_len_bytes(const M_bit_buf_t *bbuf)
M_uint8 * M_bit_buf_finish(M_bit_buf_t *bbuf, size_t *nbytes) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC
void M_bit_buf_add_bit(M_bit_buf_t *bbuf, M_uint8 bit)
const M_uint8 * M_bit_buf_peek(const M_bit_buf_t *bbuf)
@ M_BIT_BUF_PAD_AFTER
Definition: m_bit_buf.h:78
@ M_BIT_BUF_PAD_BEFORE
Definition: m_bit_buf.h:77
@ M_BIT_BUF_PAD_NONE
Definition: m_bit_buf.h:76
struct M_buf M_buf_t
Definition: m_buf.h:77