LexLeo 0.0.0-dev+f8e5087-dirty
Technical documentation
Loading...
Searching...
No Matches
stdio_stream.c
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-3.0-or-later
2 * Copyright (C) 2026 Sylvain Labopin
3 */
4
18
20
22
23#include "osal/mem/osal_mem.h"
24
26
30
32 const osal_stdio_ops_t *stdio_ops,
33 const osal_mem_ops_t *mem,
34 const stream_env_t *port_env)
35{
36 LEXLEO_ASSERT(stdio_ops && mem && port_env);
37 return
39 .stdio_ops = stdio_ops,
40 .mem = mem,
41 .port_env = *port_env
42 };
43}
44
45static size_t stdio_stream_read(
46 void *backend,
47 void *buf,
48 size_t n,
50{
51 if (!backend || (n > 0 && !buf)) {
52 if (st) *st = STREAM_STATUS_INVALID;
53 return 0;
54 }
55
56 stdio_stream_t *s = (stdio_stream_t *)backend;
57
59 s->stdio
60 && s->stdio_ops
61 && s->stdio_ops->stdin
62 );
63
64 if (s->stdio != s->stdio_ops->stdin()) {
65 if (st) *st = STREAM_STATUS_IO_ERROR;
66 return 0;
67 }
68
69 if (st) *st = STREAM_STATUS_OK;
70
71 if (n == 0)
72 return 0;
73
75
76 return s->stdio_ops->read(buf, 1, n, s->stdio);
77}
78
79static size_t stdio_stream_write(
80 void *backend,
81 const void *buf,
82 size_t n,
84{
85 if (!backend || (n > 0 && !buf)) {
86 if (st) *st = STREAM_STATUS_INVALID;
87 return 0;
88 }
89
90 stdio_stream_t *s = (stdio_stream_t *)backend;
91
93 s->stdio
94 && s->stdio_ops
95 && s->stdio_ops->stdin
96 );
97
98 if (s->stdio == s->stdio_ops->stdin()) {
99 if (st) *st = STREAM_STATUS_IO_ERROR;
100 return 0;
101 }
102
103 if (st) *st = STREAM_STATUS_OK;
104
105 if (n == 0)
106 return 0;
107
109
110 return s->stdio_ops->write(buf, 1, n, s->stdio);
111}
112
114{
115 if (!backend)
117
118 stdio_stream_t *s = (stdio_stream_t *)backend;
119
121 s->stdio
122 && s->stdio_ops
123 && s->stdio_ops->stdin
124 );
125
126 if (s->stdio == s->stdio_ops->stdin())
128
130
131 s->stdio_ops->flush(s->stdio);
132
133 return STREAM_STATUS_OK;
134}
135
137{
138 if (!backend)
140
141 stdio_stream_t *stdio_stream = (stdio_stream_t *)backend;
142
143 LEXLEO_ASSERT(stdio_stream->mem_ops && stdio_stream->mem_ops->free);
144
145 stdio_stream->mem_ops->free(stdio_stream);
146 return STREAM_STATUS_OK;
147}
148
151 .write = stdio_stream_write,
152 .flush = stdio_stream_flush,
153 .close = stdio_stream_close
154};
155
157 stream_t **out,
158 const stdio_stream_args_t *args,
159 const stdio_stream_cfg_t *cfg,
160 const stdio_stream_env_t *env)
161{
162 if (
163 !out
164 || !args
165 || !cfg
166 || !env
167 || args->kind >= STDIO_STREAM_KIND_COUNT)
168 {
170 }
171
172 LEXLEO_ASSERT(env->mem && env->mem->calloc);
173
174 stdio_stream_t *stdio_stream = env->mem->calloc(1, sizeof(*stdio_stream));
175 if (!stdio_stream) {
176 return STREAM_STATUS_OOM;
177 }
178
179 const osal_stdio_ops_t *stdio_ops = env->stdio_ops;
180
181 stdio_stream->stdio_ops = stdio_ops;
182 stdio_stream->mem_ops = env->mem;
183
185 stdio_ops
186 && stdio_ops->stdin
187 && stdio_ops->stdout
188 && stdio_ops->stderr
189 );
190
191 switch (args->kind) {
193 stdio_stream->stdio = stdio_ops->stdin();
194 break;
196 stdio_stream->stdio = stdio_ops->stdout();
197 break;
199 stdio_stream->stdio = stdio_ops->stderr();
200 break;
201 default:
202 LEXLEO_ASSERT(stdio_stream->mem_ops && stdio_stream->mem_ops->free);
203 stdio_stream->mem_ops->free(stdio_stream);
205 }
206
207 stream_t *tmp = NULL;
208
209 stream_status_t st =
211 &tmp,
213 stdio_stream,
214 &env->port_env);
215
216 if (st != STREAM_STATUS_OK) {
217 LEXLEO_ASSERT(stdio_stream->mem_ops && stdio_stream->mem_ops->free);
218 stdio_stream->mem_ops->free(stdio_stream);
219 return st;
220 }
221
222 if (!tmp) {
223 LEXLEO_ASSERT(stdio_stream->mem_ops && stdio_stream->mem_ops->free);
224 stdio_stream->mem_ops->free(stdio_stream);
225 return STREAM_STATUS_OOM;
226 }
227
228 *out = tmp;
229
230 return STREAM_STATUS_OK;
231}
232
234 const void *ud,
235 const osal_mem_ops_t *mem)
236{
237 if (!ud) {
238 return;
239 }
240
241 LEXLEO_ASSERT(mem && mem->free);
242 mem->free((void *)ud);
243}
244
247 stream_key_t key,
248 const stdio_stream_cfg_t *cfg,
249 const stdio_stream_env_t *env,
250 const osal_mem_ops_t *mem)
251{
252 if (out) {
253 *out = (stream_adapter_desc_t){0};
254 }
255
256 stream_adapter_desc_t tmp = {0};
257
258 if (
259 !out
260 || !key
261 || *key == '\0'
262 || !cfg
263 || !env
264 || !mem)
265 {
267 }
268
269 LEXLEO_ASSERT(mem->calloc && mem->free);
270
271 tmp.key = key;
273
275 (stdio_stream_ctor_ud_t *)mem->calloc(1, sizeof(*ud));
276 if (!ud) {
277 return STREAM_STATUS_OOM;
278 }
279
280 tmp.ud = ud;
281 osal_memcpy(&ud->cfg, cfg, sizeof(*cfg));
282 osal_memcpy(&ud->env, env, sizeof(*env));
284
285 *out = tmp;
286 return STREAM_STATUS_OK;
287}
288
290 const void *ud,
291 const void *args,
292 stream_t **out)
293{
294 const stdio_stream_ctor_ud_t *ctor_ud =
295 (const stdio_stream_ctor_ud_t *)ud;
296
297 if (
298 !args
299 || !out
300 || !ctor_ud)
301 {
303 }
304
305 stream_t *tmp = NULL;
306 stream_status_t st =
308 &tmp,
309 (const stdio_stream_args_t *)args,
310 &ctor_ud->cfg,
311 &ctor_ud->env);
312
313 if (st != STREAM_STATUS_OK) {
314 return st;
315 }
316
317 *out = tmp;
318 return STREAM_STATUS_OK;
319}
#define LEXLEO_ASSERT(expr)
void * osal_memcpy(void *dest, const void *src, size_t n)
Definition osal_mem.c:25
stream_status_t stdio_stream_ctor(const void *ud, const void *args, stream_t **out)
Factory-compatible constructor callback for the stdio_stream adapter.
static const stream_vtbl_t STDIO_STREAM_VTBL
static void stdio_stream_destroy_ud_ctor(const void *ud, const osal_mem_ops_t *mem)
stream_status_t stdio_stream_create_stream(stream_t **out, const stdio_stream_args_t *args, const stdio_stream_cfg_t *cfg, const stdio_stream_env_t *env)
Create a standard-I/O-backed stream instance.
stdio_stream_env_t stdio_stream_default_env(const osal_stdio_ops_t *stdio_ops, const osal_mem_ops_t *mem, const stream_env_t *port_env)
Build a default environment for the stdio_stream adapter.
static stream_status_t stdio_stream_flush(void *backend)
static stream_status_t stdio_stream_close(void *backend)
static size_t stdio_stream_write(void *backend, const void *buf, size_t n, stream_status_t *st)
stdio_stream_cfg_t stdio_stream_default_cfg(void)
Return a default configuration for the stdio_stream adapter.
stream_status_t stdio_stream_create_desc(stream_adapter_desc_t *out, stream_key_t key, const stdio_stream_cfg_t *cfg, const stdio_stream_env_t *env, const osal_mem_ops_t *mem)
Build a stream adapter descriptor for the stdio_stream adapter.
static size_t stdio_stream_read(void *backend, void *buf, size_t n, stream_status_t *st)
Composition Root API for wiring the stdio_stream adapter into the stream factory.
Private constructor user-data stored in stdio_stream factory descriptors.
Private backend handle definition for the stdio_stream adapter.
@ STDIO_STREAM_KIND_STDERR
Standard error stream.
@ STDIO_STREAM_KIND_STDOUT
Standard output stream.
@ STDIO_STREAM_KIND_STDIN
Standard input stream.
@ STDIO_STREAM_KIND_COUNT
Number of supported standard I/O stream kinds.
stream_status_t stream_create(stream_t **out, const stream_vtbl_t *vtbl, void *backend, const stream_env_t *env)
Create a generic stream handle from adapter-provided backend bindings.
Definition stream.c:69
Public environment type for the stream port.
const char * stream_key_t
Public identifier type for a registered stream adapter.
stream_status_t
Public status codes used by the stream port.
@ STREAM_STATUS_INVALID
@ STREAM_STATUS_IO_ERROR
@ STREAM_STATUS_OK
@ STREAM_STATUS_OOM
void *(* calloc)(size_t nmemb, size_t size)
void(* free)(void *ptr)
OSAL_STDIO *(* stdin)(void)
size_t(* write)(const void *ptr, size_t size, size_t nmemb, OSAL_STDIO *stdio)
size_t(* read)(void *ptr, size_t size, size_t nmemb, OSAL_STDIO *stdio)
OSAL_STDIO *(* stderr)(void)
OSAL_STDIO *(* stdout)(void)
int(* flush)(OSAL_STDIO *stdio)
Creation arguments for the stdio_stream adapter.
stdio_stream_kind_t kind
Requested standard I/O stream kind.
Configuration type for the stdio_stream adapter.
int reserved
Reserved configuration field.
Private constructor user-data for stdio_stream factory registration.
Injected dependencies for the stdio_stream adapter.
const osal_stdio_ops_t * stdio_ops
Borrowed OSAL stdio operations table.
stream_env_t port_env
Borrowed stream port environment.
const osal_mem_ops_t * mem
Borrowed memory operations table for adapter-owned allocations.
Private backend handle for the stdio_stream adapter.
const osal_mem_ops_t * mem_ops
const osal_stdio_ops_t * stdio_ops
Public descriptor used to register a concrete stream adapter.
stream_key_t key
Public key used to identify the adapter.
const void * ud
Optional opaque user data bound to the constructor.
ud_dtor_fn_t ud_dtor
Optional destructor for ud.
stream_ctor_fn_t ctor
Adapter constructor used to create a stream_t.
Runtime environment for the stream port.
Definition stream_env.h:35
Private handle structure for a stream_t.
Adapter dispatch table bound to a stream_t instance.
stream_read_fn_t read