LexLeo 0.0.0-dev+f8e5087-dirty
Technical documentation
Loading...
Searching...
No Matches
fs_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
15
17
18#include "osal/mem/osal_mem.h"
19
21
23 switch (osal_st) {
24 case OSAL_FILE_OK:
25 return STREAM_STATUS_OK;
26
27 case OSAL_FILE_EOF:
28 return STREAM_STATUS_EOF;
29
30 case OSAL_FILE_ERR:
31 case OSAL_FILE_IO:
32 case OSAL_FILE_NOENT:
33 case OSAL_FILE_PERM:
34 case OSAL_FILE_NOSYS:
36
37 default:
39 }
40}
41
42static size_t fs_stream_read(
43 void *backend,
44 void* buf,
45 size_t n,
46 stream_status_t *st )
47{
48 fs_stream_t *fs_stream = (fs_stream_t *)backend;
49 if (!fs_stream || (!buf && n)) {
50 if (st) *st = STREAM_STATUS_INVALID;
51 return (size_t)0;
52 }
53 if (!fs_stream->state.f && n) {
54 if (st) *st = STREAM_STATUS_NO_BACKEND;
55 return (size_t)0;
56 }
58 size_t s = fs_stream->file_ops->read(fs_stream->state.f, buf, n, &osal_st);
59 if (st) *st = map_osal_status(osal_st);
60 return s;
61}
62
63static size_t fs_stream_write(
64 void *backend,
65 const void* buf,
66 size_t n,
67 stream_status_t *st )
68{
69 fs_stream_t *fs_stream = (fs_stream_t *)backend;
70 if (!fs_stream || (!buf && n)) {
71 if (st) *st = STREAM_STATUS_INVALID;
72 return (size_t)0;
73 }
74 if (!fs_stream->state.f && n) {
75 if (st) *st = STREAM_STATUS_NO_BACKEND;
76 return (size_t)0;
77 }
79 size_t s =
80 fs_stream->file_ops->write(
81 fs_stream->state.f, buf, n, &osal_st );
82
83 if (st)
84 *st =
85 (osal_st == OSAL_FILE_EOF) ?
87 :
88 map_osal_status(osal_st);
89 return s;
90}
91
92static stream_status_t fs_stream_flush(void *backend) {
93 fs_stream_t *fs_stream = (fs_stream_t *)backend;
94 if (!fs_stream)
96 if (!fs_stream->state.f)
98
99 osal_file_status_t osal_st =
100 fs_stream->file_ops->flush(
101 fs_stream->state.f );
102
103 if (osal_st == OSAL_FILE_EOF)
105
106 return map_osal_status(osal_st);
107}
108
109static stream_status_t fs_stream_close(void *backend) {
110 fs_stream_t *fs_stream = (fs_stream_t *)backend;
111 if (!fs_stream) return STREAM_STATUS_INVALID;
112
114
115 if (fs_stream->state.f && fs_stream->state.autoclose) {
116 osal_st = fs_stream->file_ops->close(fs_stream->state.f);
117 }
118 fs_stream->state.f = NULL;
119
120 LEXLEO_ASSERT(fs_stream->mem_ops && fs_stream->mem_ops->free);
121 fs_stream->mem_ops->free(fs_stream);
122
123 if (osal_st == OSAL_FILE_EOF) return STREAM_STATUS_IO_ERROR;
124 return map_osal_status(osal_st);
125}
126
127static const stream_vtbl_t VTBL = {
129 .write = fs_stream_write,
130 .flush = fs_stream_flush,
131 .close = fs_stream_close
132};
133
135 fs_stream_t **out,
136 const fs_stream_args_t *args,
137 const fs_stream_cfg_t *cfg,
138 const fs_stream_env_t *env)
139{
140 if (
141 !out
142 || !args
143 || args->path == NULL
144 || *args->path == '\0'
145 || args->flags == 0
146 || !cfg
147 || !env ) {
149 }
150
151 LEXLEO_ASSERT(env->file_ops != NULL);
152 LEXLEO_ASSERT(env->file_env.mem != NULL);
153
154 fs_stream_t *backend =
155 (fs_stream_t *)env->file_env.mem->calloc(1, sizeof(*backend));
156 if (!backend) {
157 return STREAM_STATUS_OOM;
158 }
159
160 backend->mem_ops = env->file_env.mem;
161 backend->file_ops = env->file_ops;
162
164 backend->state.f =
165 backend->file_ops->open(
166 args->path,
167 args->flags,
168 &st,
169 &env->file_env );
170
172 if (!backend->state.f || sst != STREAM_STATUS_OK) {
173 env->file_env.mem->free(backend);
174 return (sst != STREAM_STATUS_OK) ? sst : STREAM_STATUS_IO_ERROR;
175 }
176
177 backend->state.autoclose = args->autoclose;
178
179 *out = backend;
180 return STREAM_STATUS_OK;
181}
182
184{
185 if (!p || !*p) return;
186 fs_stream_t *b = *p;
187 *p = NULL;
188
189 if (b->state.f && b->file_ops && b->file_ops->close) {
190 (void)b->file_ops->close(b->state.f);
191 b->state.f = NULL;
192 }
193
194 if (b->mem_ops && b->mem_ops->free) {
195 b->mem_ops->free(b);
196 }
197}
198
200 const void *ud,
201 const osal_mem_ops_t *mem ) // MUST BE THE FACTORY'S
202{
203 if (!ud) return;
204 LEXLEO_ASSERT(mem && mem->free);
205 mem->free((void*)ud);
206}
207
209 stream_t **out,
210 const fs_stream_args_t *args,
211 const fs_stream_cfg_t *cfg,
212 const fs_stream_env_t *env )
213{
214 if (!out || !env) {
216 }
217
218 fs_stream_t *backend = NULL;
219 stream_status_t st = create_backend(&backend, args, cfg, env);
220 if (st != STREAM_STATUS_OK) return st;
221
222 stream_t *tmp = NULL;
223 st = stream_create(&tmp, &VTBL, backend, &env->port_env);
224 if (st != STREAM_STATUS_OK) {
225 destroy_backend(&backend);
226 return st;
227 }
228
229 *out = tmp;
230 return STREAM_STATUS_OK;
231}
232
234 const void *ud,
235 const void *args,
236 stream_t **out )
237{
238 const fs_stream_ctor_ud_t *ctor_ud =
239 (const fs_stream_ctor_ud_t *) ud;
240
241 if (!out || !args || !ctor_ud) {
243 }
244
245 stream_t *tmp = NULL;
246 stream_status_t st =
248 &tmp,
249 (const fs_stream_args_t *)args,
250 &ctor_ud->cfg,
251 &ctor_ud->env );
252 if (st == STREAM_STATUS_OK) *out = tmp;
253 return st;
254}
255
258 stream_key_t key,
259 const fs_stream_cfg_t *cfg,
260 const fs_stream_env_t *env,
261 const osal_mem_ops_t *mem ) // MUST BE THE FACTORY'S
262{
263 if (out) *out = (stream_adapter_desc_t){0};
264
265 stream_adapter_desc_t tmp = {0};
266
267 if (
268 !out
269 || !key
270 || *key == '\0'
271 || !cfg
272 || !env
273 || !mem
274 || !env->file_env.mem
275 || !env->file_ops )
277
278 tmp.key = key;
279 tmp.ctor = fs_stream_ctor;
280
281 fs_stream_ctor_ud_t *ud = mem->calloc(1, sizeof(*ud));
282 if (!ud)
283 return STREAM_STATUS_OOM;
284
285 tmp.ud = ud;
286 osal_memcpy(&ud->cfg, cfg, sizeof(*cfg));
287 osal_memcpy(&ud->env, env, sizeof(*env));
289
290 *out = tmp;
291 return STREAM_STATUS_OK;
292}
293
297
299 const osal_file_env_t *file_env,
300 const osal_file_ops_t *file_ops,
301 const stream_env_t *port_env )
302{
303 LEXLEO_ASSERT(file_env);
304 LEXLEO_ASSERT(file_ops);
305 LEXLEO_ASSERT(port_env);
306
307 return (fs_stream_env_t){
308 .file_env = *file_env,
309 .file_ops = file_ops,
310 .port_env = *port_env
311 };
312}
stream_status_t fs_stream_create_stream(stream_t **out, const fs_stream_args_t *args, const fs_stream_cfg_t *cfg, const fs_stream_env_t *env)
Create a file-backed stream instance.
Definition fs_stream.c:208
static stream_status_t create_backend(fs_stream_t **out, const fs_stream_args_t *args, const fs_stream_cfg_t *cfg, const fs_stream_env_t *env)
Definition fs_stream.c:134
fs_stream_cfg_t fs_stream_default_cfg(void)
Return a default configuration for the fs_stream adapter.
Definition fs_stream.c:294
static stream_status_t fs_stream_close(void *backend)
Definition fs_stream.c:109
stream_status_t fs_stream_ctor(const void *ud, const void *args, stream_t **out)
Factory constructor callback for the fs_stream adapter.
Definition fs_stream.c:233
stream_status_t fs_stream_create_desc(stream_adapter_desc_t *out, stream_key_t key, const fs_stream_cfg_t *cfg, const fs_stream_env_t *env, const osal_mem_ops_t *mem)
Build an adapter descriptor for registering fs_stream in a factory.
Definition fs_stream.c:256
static void destroy_backend(fs_stream_t **p)
Definition fs_stream.c:183
static size_t fs_stream_read(void *backend, void *buf, size_t n, stream_status_t *st)
Definition fs_stream.c:42
static size_t fs_stream_write(void *backend, const void *buf, size_t n, stream_status_t *st)
Definition fs_stream.c:63
static void fs_stream_destroy_ud_ctor(const void *ud, const osal_mem_ops_t *mem)
Definition fs_stream.c:199
static stream_status_t fs_stream_flush(void *backend)
Definition fs_stream.c:92
static stream_status_t map_osal_status(osal_file_status_t osal_st)
Definition fs_stream.c:22
static const stream_vtbl_t VTBL
Definition fs_stream.c:127
fs_stream_env_t fs_stream_default_env(const osal_file_env_t *file_env, const osal_file_ops_t *file_ops, const stream_env_t *port_env)
Build a default environment for the fs_stream adapter.
Definition fs_stream.c:298
Composition Root API for wiring the fs_stream adapter into the stream factory.
Private constructor user-data stored in fs_stream factory descriptors.
Private backend handle definition for the fs_stream adapter.
osal_file_status_t
@ OSAL_FILE_EOF
@ OSAL_FILE_PERM
@ OSAL_FILE_NOSYS
@ OSAL_FILE_OK
@ OSAL_FILE_IO
@ OSAL_FILE_NOENT
@ OSAL_FILE_ERR
#define LEXLEO_ASSERT(expr)
void * osal_memcpy(void *dest, const void *src, size_t n)
Definition osal_mem.c:25
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
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_EOF
@ STREAM_STATUS_IO_ERROR
@ STREAM_STATUS_OK
@ STREAM_STATUS_OOM
@ STREAM_STATUS_NO_BACKEND
Arguments provided when creating a file-backed stream.
bool autoclose
Whether the OSAL file must be closed when the stream is destroyed.
const char * path
UTF-8 path of the target file.
uint32_t flags
OSAL file open flags.
Configuration type for the fs_stream adapter.
int reserved
Reserved configuration field.
Private constructor user-data for fs_stream factory registration.
Injected dependencies for the fs_stream adapter.
osal_file_env_t file_env
Borrowed OSAL file environment.
stream_env_t port_env
Borrowed stream port environment.
const osal_file_ops_t * file_ops
Borrowed OSAL file operations table.
Private backend handle for the fs_stream adapter.
const osal_mem_ops_t * mem_ops
fs_stream_state_t state
const osal_file_ops_t * file_ops
const osal_mem_ops_t * mem
size_t(* write)(osal_file_t *f, const void *buf, size_t n, osal_file_status_t *status)
osal_file_status_t(* close)(osal_file_t *f)
osal_file_status_t(* flush)(osal_file_t *f)
size_t(* read)(osal_file_t *f, void *buf, size_t n, osal_file_status_t *status)
osal_file_t *(* open)(const char *path_utf8, uint32_t flags, osal_file_status_t *status, const osal_file_env_t *env)
void *(* calloc)(size_t nmemb, size_t size)
void(* free)(void *ptr)
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