ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
output_buffer.c
Go to the documentation of this file.
1
8#include "common.h"
9
10/*****************************************************************************/
11// char* output buffer helpers
12//
13// ob_* - build strings with an output buffer
14// ob_reserve - reserve space in the output buffer
15// ob_putc - append a single character to the output buffer
16// ob_write - append a string to the output buffer
17// ob_term - terminate the output buffer
18// ob_u8 - append a decimal number to the output buffer
19// ob_u32 - append a decimal number to the output buffer
20
21void ob_reserve(outbuf_t *ob, size_t need) {
22 if (!ob)
23 return;
24 if (ob->cap == 0) {
25 // Always allocate at least default capacity on first call
26 size_t ncap = 4096;
27 while (ncap < ob->len + need)
28 ncap = (ncap * 3) / 2;
29 // SAFE_REALLOC handles NULL ptr as malloc - this is safe
30 ob->buf = SAFE_REALLOC(ob->buf, ncap, char *);
31 ob->cap = ncap;
32 } else if (ob->len + need > ob->cap) {
33 // Expand existing buffer
34 size_t ncap = ob->cap;
35 while (ncap < ob->len + need)
36 ncap = (ncap * 3) / 2;
37 ob->buf = SAFE_REALLOC(ob->buf, ncap, char *);
38 ob->cap = ncap;
39 }
40}
41
42void ob_putc(outbuf_t *ob, char c) {
43 if (!ob)
44 return;
45 ob_reserve(ob, 1);
46 ob->buf[ob->len++] = c;
47}
48
49void ob_write(outbuf_t *ob, const char *s, size_t n) {
50 if (!ob || n == 0)
51 return;
52 ob_reserve(ob, n);
53 SAFE_MEMCPY(ob->buf + ob->len, ob->cap - ob->len, s, n);
54 ob->len += n;
55}
56
57void ob_term(outbuf_t *ob) {
58 if (!ob)
59 return;
60 ob_putc(ob, '\0');
61}
62
63// Fast decimal for uint8_t (0..255)
64void ob_u8(outbuf_t *ob, uint8_t v) {
65 if (!ob)
66 return;
67 if (v >= 100) {
68 uint8_t d0 = v / 100;
69 uint8_t r = v % 100;
70 uint8_t d1 = r / 10;
71 uint8_t d2 = r % 10;
72 ob_putc(ob, '0' + d0);
73 ob_putc(ob, '0' + d1);
74 ob_putc(ob, '0' + d2);
75 } else if (v >= 10) {
76 uint8_t d1 = v / 10;
77 uint8_t d2 = v % 10;
78 ob_putc(ob, '0' + d1);
79 ob_putc(ob, '0' + d2);
80 } else {
81 ob_putc(ob, '0' + v);
82 }
83}
84
85void ob_u32(outbuf_t *ob, uint32_t v) {
86 if (!ob)
87 return;
88 char tmp[10];
89 int i = 0;
90 do {
91 tmp[i++] = '0' + (v % 10u);
92 v /= 10u;
93 } while (v);
94 ob_reserve(ob, (size_t)i);
95 while (i--)
96 ob->buf[ob->len++] = tmp[i];
97}
98
99// Truecolor SGR emission (foreground)
101 if (!ob)
102 return;
103 // ESC[38;2;R;G;Bm
104 ob_putc(ob, 0x1b);
105 ob_putc(ob, '[');
106 ob_write(ob, "38;2;", 5);
107 ob_u8(ob, r);
108 ob_putc(ob, ';');
109 ob_u8(ob, g);
110 ob_putc(ob, ';');
111 ob_u8(ob, b);
112 ob_putc(ob, 'm');
113}
114
115// Truecolor SGR emission (background)
117 if (!ob)
118 return;
119 // ESC[48;2;R;G;Bm
120 ob_putc(ob, 0x1b);
121 ob_putc(ob, '[');
122 ob_write(ob, "48;2;", 5);
123 ob_u8(ob, r);
124 ob_putc(ob, ';');
125 ob_u8(ob, g);
126 ob_putc(ob, ';');
127 ob_u8(ob, b);
128 ob_putc(ob, 'm');
129}
130
132 if (!ob)
133 return;
134 ob_putc(ob, 0x1b);
135 ob_putc(ob, '[');
136 ob_putc(ob, '0');
137 ob_putc(ob, 'm');
138}
139
140// REP profitability calculation
142 if (runlen <= 2)
143 return false;
144 uint32_t k = runlen - 1; // Extra repetitions beyond the first character
145 uint32_t rep_cost = (uint32_t)(digits_u32(k) + 3); // ESC [ digits b
146 return k > rep_cost; // Manual repetition cost vs REP cost
147}
148
149void emit_rep(outbuf_t *ob, uint32_t extra) {
150 if (!ob)
151 return;
152 // ESC [ extra b
153 ob_putc(ob, 0x1b);
154 ob_putc(ob, '[');
155 ob_u32(ob, extra);
156 ob_putc(ob, 'b');
157}
158
159// 256-color SGR emission (foreground)
161 if (!ob)
162 return;
163 // ESC[38;5;Nm
164 ob_putc(ob, 0x1b);
165 ob_putc(ob, '[');
166 ob_write(ob, "38;5;", 5);
167 ob_u8(ob, color_idx);
168 ob_putc(ob, 'm');
169}
170
171// 256-color SGR emission (background)
173 if (!ob)
174 return;
175 // ESC[48;5;Nm
176 ob_putc(ob, 0x1b);
177 ob_putc(ob, '[');
178 ob_write(ob, "48;5;", 5);
179 ob_u8(ob, color_idx);
180 ob_putc(ob, 'm');
181}
182
184 if (!ob)
185 return;
186 // ESC[38;2;R;G;Bm
187 ob_putc(ob, 0x1b);
188 ob_putc(ob, '[');
189 ob_write(ob, "38;2;", 5);
190 ob_u8(ob, r);
191 ob_putc(ob, ';');
192 ob_u8(ob, g);
193 ob_putc(ob, ';');
194 ob_u8(ob, b);
195 ob_putc(ob, 'm');
196}
197
199 if (!ob)
200 return;
201 // ESC[48;2;R;G;Bm
202 ob_putc(ob, 0x1b);
203 ob_putc(ob, '[');
204 ob_write(ob, "48;2;", 5);
205 ob_u8(ob, r);
206 ob_putc(ob, ';');
207 ob_u8(ob, g);
208 ob_putc(ob, ';');
209 ob_u8(ob, b);
210 ob_putc(ob, 'm');
211}
#define SAFE_REALLOC(ptr, size, cast)
Definition common.h:228
unsigned int uint32_t
Definition common.h:58
unsigned char uint8_t
Definition common.h:56
#define SAFE_MEMCPY(dest, dest_size, src, count)
Definition common.h:388
void emit_set_256_color_bg(outbuf_t *ob, uint8_t color_idx)
Emit 256-color background ANSI sequence.
void emit_set_bg(outbuf_t *ob, uint8_t r, uint8_t g, uint8_t b)
Emit background color sequence (auto-select mode)
void ob_u32(outbuf_t *ob, uint32_t v)
Append unsigned 32-bit integer as decimal string.
void ob_u8(outbuf_t *ob, uint8_t v)
Append unsigned 8-bit integer as decimal string.
void emit_set_256_color_fg(outbuf_t *ob, uint8_t color_idx)
Emit 256-color foreground ANSI sequence.
void ob_term(outbuf_t *ob)
Append null terminator to buffer.
void ob_putc(outbuf_t *ob, char c)
Append a character to buffer.
bool rep_is_profitable(uint32_t runlen)
Check if run-length encoding is profitable.
void ob_reserve(outbuf_t *ob, size_t need)
Reserve buffer space for upcoming writes.
void emit_set_truecolor_fg(outbuf_t *ob, uint8_t r, uint8_t g, uint8_t b)
Emit truecolor foreground ANSI sequence.
void emit_rep(outbuf_t *ob, uint32_t extra)
Emit run-length encoded sequence.
void ob_write(outbuf_t *ob, const char *s, size_t n)
Append a string to buffer.
void emit_reset(outbuf_t *ob)
Emit ANSI reset sequence.
void emit_set_truecolor_bg(outbuf_t *ob, uint8_t r, uint8_t g, uint8_t b)
Emit truecolor background ANSI sequence.
void emit_set_fg(outbuf_t *ob, uint8_t r, uint8_t g, uint8_t b)
Emit foreground color sequence (auto-select mode)
Dynamic Output Buffer with ANSI Sequence Support.
Dynamic output buffer (auto-expanding)
size_t cap
Buffer capacity in bytes (maximum length before reallocation)
size_t len
Current length in bytes (excluding null terminator)
char * buf
Buffer pointer (allocated, owned by caller, must be freed)