ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
output_buffer.c
Go to the documentation of this file.
1
8#include <ascii-chat/common.h>
10
11/*****************************************************************************/
12// char* output buffer helpers
13//
14// ob_* - build strings with an output buffer
15// ob_reserve - reserve space in the output buffer
16// ob_putc - append a single character to the output buffer
17// ob_write - append a string to the output buffer
18// ob_term - terminate the output buffer
19// ob_u8 - append a decimal number to the output buffer
20// ob_u32 - append a decimal number to the output buffer
21
22void ob_reserve(outbuf_t *ob, size_t need) {
23 if (!ob)
24 return;
25 if (ob->cap == 0) {
26 // Always allocate at least default capacity on first call
27 size_t ncap = 4096;
28 while (ncap < ob->len + need)
29 ncap = (ncap * 3) / 2;
30 // SAFE_REALLOC handles NULL ptr as malloc - this is safe
31 ob->buf = SAFE_REALLOC(ob->buf, ncap, char *);
32 ob->cap = ncap;
33 } else if (ob->len + need > ob->cap) {
34 // Expand existing buffer
35 size_t ncap = ob->cap;
36 while (ncap < ob->len + need)
37 ncap = (ncap * 3) / 2;
38 ob->buf = SAFE_REALLOC(ob->buf, ncap, char *);
39 ob->cap = ncap;
40 }
41}
42
43void ob_putc(outbuf_t *ob, char c) {
44 if (!ob)
45 return;
46 ob_reserve(ob, 1);
47 ob->buf[ob->len++] = c;
48}
49
50void ob_write(outbuf_t *ob, const char *s, size_t n) {
51 if (!ob || n == 0)
52 return;
53 ob_reserve(ob, n);
54 SAFE_MEMCPY(ob->buf + ob->len, ob->cap - ob->len, s, n);
55 ob->len += n;
56}
57
58void ob_term(outbuf_t *ob) {
59 if (!ob)
60 return;
61 // Reserve space for null terminator if needed
62 if (ob->len >= ob->cap) {
63 ob_reserve(ob, 1);
64 }
65 // Append null terminator WITHOUT incrementing length
66 // (null terminator is not part of the string length)
67 ob->buf[ob->len] = '\0';
68}
69
70// Fast decimal for uint8_t (0..255)
71void ob_u8(outbuf_t *ob, uint8_t v) {
72 if (!ob)
73 return;
74 if (v >= 100) {
75 uint8_t d0 = v / 100;
76 uint8_t r = v % 100;
77 uint8_t d1 = r / 10;
78 uint8_t d2 = r % 10;
79 ob_putc(ob, '0' + d0);
80 ob_putc(ob, '0' + d1);
81 ob_putc(ob, '0' + d2);
82 } else if (v >= 10) {
83 uint8_t d1 = v / 10;
84 uint8_t d2 = v % 10;
85 ob_putc(ob, '0' + d1);
86 ob_putc(ob, '0' + d2);
87 } else {
88 ob_putc(ob, '0' + v);
89 }
90}
91
92void ob_u32(outbuf_t *ob, uint32_t v) {
93 if (!ob)
94 return;
95 char tmp[10];
96 int i = 0;
97 do {
98 tmp[i++] = '0' + (v % 10u);
99 v /= 10u;
100 } while (v);
101 ob_reserve(ob, (size_t)i);
102 while (i--)
103 ob->buf[ob->len++] = tmp[i];
104}
105
106// Truecolor SGR emission (foreground)
108 if (!ob)
109 return;
110 // ESC[38;2;R;G;Bm
111 ob_putc(ob, 0x1b);
112 ob_putc(ob, '[');
113 ob_write(ob, "38;2;", 5);
114 ob_u8(ob, r);
115 ob_putc(ob, ';');
116 ob_u8(ob, g);
117 ob_putc(ob, ';');
118 ob_u8(ob, b);
119 ob_putc(ob, 'm');
120}
121
122// Truecolor SGR emission (background)
124 if (!ob)
125 return;
126 // ESC[48;2;R;G;Bm
127 ob_putc(ob, 0x1b);
128 ob_putc(ob, '[');
129 ob_write(ob, "48;2;", 5);
130 ob_u8(ob, r);
131 ob_putc(ob, ';');
132 ob_u8(ob, g);
133 ob_putc(ob, ';');
134 ob_u8(ob, b);
135 ob_putc(ob, 'm');
136}
137
139 if (!ob)
140 return;
141 ob_putc(ob, 0x1b);
142 ob_putc(ob, '[');
143 ob_putc(ob, '0');
144 ob_putc(ob, 'm');
145}
146
147// REP profitability calculation
149 if (runlen <= 2)
150 return false;
151 uint32_t k = runlen - 1; // Extra repetitions beyond the first character
152 uint32_t rep_cost = (uint32_t)(digits_u32(k) + 3); // ESC [ digits b
153 return k > rep_cost; // Manual repetition cost vs REP cost
154}
155
156void emit_rep(outbuf_t *ob, uint32_t extra) {
157 if (!ob)
158 return;
159 // ESC [ extra b
160 ob_putc(ob, 0x1b);
161 ob_putc(ob, '[');
162 ob_u32(ob, extra);
163 ob_putc(ob, 'b');
164}
165
166// 256-color SGR emission (foreground) - uses cached sequences for performance
168 if (!ob)
169 return;
170 // Use pre-cached color sequence instead of building on-demand
171 uint8_t seq_len;
172 const char *seq = get_sgr256_fg_string(color_idx, &seq_len);
173 ob_write(ob, seq, seq_len);
174}
175
176// 256-color SGR emission (background) - uses cached sequences for performance
178 if (!ob)
179 return;
180 // Use pre-cached color sequence instead of building on-demand
181 uint8_t seq_len;
182 const char *seq = get_sgr256_bg_string(color_idx, &seq_len);
183 ob_write(ob, seq, seq_len);
184}
185
187 if (!ob)
188 return;
189 // ESC[38;2;R;G;Bm
190 ob_putc(ob, 0x1b);
191 ob_putc(ob, '[');
192 ob_write(ob, "38;2;", 5);
193 ob_u8(ob, r);
194 ob_putc(ob, ';');
195 ob_u8(ob, g);
196 ob_putc(ob, ';');
197 ob_u8(ob, b);
198 ob_putc(ob, 'm');
199}
200
202 if (!ob)
203 return;
204 // ESC[48;2;R;G;Bm
205 ob_putc(ob, 0x1b);
206 ob_putc(ob, '[');
207 ob_write(ob, "48;2;", 5);
208 ob_u8(ob, r);
209 ob_putc(ob, ';');
210 ob_u8(ob, g);
211 ob_putc(ob, ';');
212 ob_u8(ob, b);
213 ob_putc(ob, 'm');
214}
⚙️ Common definitions, error codes, macros, and types shared throughout the application
#define SAFE_REALLOC(ptr, size, cast)
Definition common.h:284
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:468
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.
char * get_sgr256_bg_string(uint8_t bg, uint8_t *len_out)
Get 256-color background ANSI sequence string.
Definition sgr.c:142
void emit_set_truecolor_bg(outbuf_t *ob, uint8_t r, uint8_t g, uint8_t b)
Emit truecolor background ANSI sequence.
char * get_sgr256_fg_string(uint8_t fg, uint8_t *len_out)
Get 256-color foreground ANSI sequence string.
Definition sgr.c:134
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 (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)
SIMD-optimized ASCII conversion interface.