MMgr v1.0.0
Zero-heap memory manager in C11. One borrowed buffer, carved by asserted offset.
Loading...
Searching...
No Matches
bitorum_introitus_exitus.h
Go to the documentation of this file.
1/* MMgr - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2 * SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Commercial OR LicenseRef-Educational
3 *
4 * Every use falls under AGPL-3.0-or-later unless you hold explicit permission, which is either a
5 * negotiated commercial licensing contract or an educator's license issued to you personally.
6 */
7/**
8 * @file bitorum_introitus_exitus.h
9 * @brief Bit writer state, its arguments, and the bitio dispatch table.
10 * @author dstroy0 (Douglas Quigg) <dquigg123@gmail.com>
11 * @date 2026-08-29
12 *
13 * @note Packs bit fields of any width into a byte buffer without a bit ever crossing a call. The
14 * writer holds the partial byte. A caller states widths and values and never does its own
15 * shifting or masking.
16 * @note The writer is a value the caller owns and not state this module keeps. Two streams are two
17 * writers, and neither module state nor a lock is involved.
18 * @warning put writes whole bytes only, and so bits that do not fill one stay in the writer's residue
19 * and align puts that last partial byte out. A stream whose length is not a
20 * multiple of eight and that never calls align ends one byte short, with no flag raised
21 * and nothing to notice at the call.
22 */
23#ifndef MMGR_BITORUM_INTROITUS_EXITUS_H
24#define MMGR_BITORUM_INTROITUS_EXITUS_H
25
26#include "mmgr.h"
27
28EMBED_BEGIN_DECLS
29
30/**
31 * @brief Bit writer state: the buffer, how much is written, and the partial byte.
32 *
33 * @note Built by mmgr_bitor_init, advanced by mmgr_bitor_put, and finished by mmgr_bitor_align.
34 */
35typedef struct
36{
37 uint8_t *out; /**< Destination buffer [BORROWS]. */
38 size_t cap; /**< Bytes available in out. */
39 size_t bytes_written; /**< Whole bytes written so far. */
40 uint8_t residue; /**< Bits not yet written, in the low bit_count positions. */
41 embed_word bit_count; /**< Bits stored in residue, always under 8. */
42 embed_bool overflow; /**< Set once a request would pass cap, which blocks later writes. */
44
45/**
46 * @brief Arguments for the bitor calls, where each call reads only the members it needs.
47 *
48 * @note mmgr_bitor_init reads out and cap. mmgr_bitor_put reads writer, val and bit_count.
49 * mmgr_bitor_align reads writer alone.
50 * @note One argument type for all three entries, and so every call has the same shape and an unnamed
51 * member is zeroed and not left undefined.
52 */
53typedef struct
54{
55 mmgr_bitor *const writer; /**< Writer for mmgr_bitor_put and mmgr_bitor_align [BORROWS]. */
56 uint8_t *const out; /**< Buffer for mmgr_bitor_init [BORROWS]. */
57 const size_t cap; /**< Bytes available in out. */
58 const uint64_t val; /**< Bits for mmgr_bitor_put, taken from the low end. */
59 const embed_word bit_count; /**< Bits of val to write, which must not exceed 64. */
61
62/**
63 * @brief Type of the bitio dispatch table.
64 *
65 * @note EMBED_TABLE_LAYOUT asserts the three members sit at consecutive EMBED_FUNCTION_POINTER_BYTES offsets, with
66 * nothing else.
67 */
68typedef struct
69{
70 mmgr_bitor (*init)(const BitorumCfg *args); /**< Builds a writer over a buffer. */
71 void (*put)(const BitorumCfg *args); /**< Appends bits, writing whole bytes only. */
72 void (*align)(const BitorumCfg *args); /**< Writes the partial byte still pending. */
74EMBED_TABLE_LAYOUT(BitorumIntroitusExitusNs, init, put, align);
75
76/**
77 * @brief Builds a bit writer over args->out with capacity args->cap.
78 *
79 * @param[in] args Buffer and capacity [BORROWS].
80 * @return A writer with no bytes written and no residue.
81 * @note The returned writer keeps args->out, which must outlive it [BORROWS].
82 * @warning args->out must not be null and args->cap must not be zero. Neither is checked outside a
83 * MMGR_DEBUG_CHECKS build, and a null out is not noticed here: mmgr_bitor_put writes
84 * through it on the first whole byte.
85 */
87
88/**
89 * @brief Appends the low args->bit_count bits of args->val to args->writer.
90 *
91 * @param[in,out] args Writer, value and bit count [BORROWS].
92 * @note Writes whole bytes only. Leftover bits stay in the writer's residue.
93 * @note Does nothing when the writer's overflow is already set. A caller may write a whole
94 * stream and test overflow once at the end and not after every call.
95 * @note Sets the writer's overflow and clears its residue when the bytes would pass its cap.
96 * @warning args->bit_count must not exceed 64, and nothing holds it there outside a
97 * MMGR_DEBUG_CHECKS build. A larger count writes zeros past the sixty-fourth bit and
98 * advances the writer as though they were data.
99 */
100void mmgr_bitor_put(const BitorumCfg *args);
101
102/**
103 * @brief Writes the partial byte the writer still holds, padded with zeros above its bits.
104 *
105 * @param[in,out] args Writer to finish [BORROWS].
106 * @note mmgr_bitor_put writes whole bytes only. Without this call the residue is never written.
107 * @note Does nothing when the residue is empty. A second call writes nothing.
108 * @note Does nothing when the writer's overflow is already set.
109 * @note Only args->writer is read.
110 * @warning Sets the writer's overflow when the byte would pass its cap.
111 */
112void mmgr_bitor_align(const BitorumCfg *args);
113
114/**
115 * @brief Dispatch table instance named bitio, with each member set to its mmgr_bitor_ function.
116 */
117EMBED_TABLE_STORAGE BitorumIntroitusExitusNs bitio EMBED_UNUSED = {
118 .init = mmgr_bitor_init,
119 .put = mmgr_bitor_put,
120 .align = mmgr_bitor_align,
121};
122
123EMBED_END_DECLS
124
125#endif
static const BitorumIntroitusExitusNs bitio
Dispatch table instance named bitio, with each member set to its mmgr_bitor_ function.
void mmgr_bitor_align(const BitorumCfg *args)
Writes the partial byte the writer still holds, padded with zeros above its bits.
mmgr_bitor mmgr_bitor_init(const BitorumCfg *args)
Builds a bit writer over args->out with capacity args->cap.
void mmgr_bitor_put(const BitorumCfg *args)
Appends the low args->bit_count bits of args->val to args->writer.
The embedded_types headers every module builds on.
Arguments for the bitor calls, where each call reads only the members it needs.
const embed_word bit_count
mmgr_bitor *const writer
Type of the bitio dispatch table.
void(*) put(const BitorumCfg *args)
void(*) align(const BitorumCfg *args)
mmgr_bitor(*) init(const BitorumCfg *args)
Bit writer state: the buffer, how much is written, and the partial byte.