Skip to content

Commit 687bfce

Browse files
committed
x: Add x_fopencookie().
Implement x_fopencookie() in terms of either fopencookie or funopen, if either is available. If none of these calls are available, we don't provide x_fopencookie(). This is a draft version, notably the mode field is ignored at the moment. Tests are also missing.
1 parent ef0561c commit 687bfce

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

src/csnip/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,16 @@ check_symbol_exists(clock_gettime "time.h"
4545
CSNIP_CONF__HAVE_CLOCK_GETTIME)
4646
check_symbol_exists(flockfile "stdio.h"
4747
CSNIP_CONF__HAVE_FLOCKFILE)
48+
set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
49+
check_symbol_exists(fopencookie "stdio.h"
50+
CSNIP_CONF__HAVE_FOPENCOOKIE)
51+
unset(CMAKE_REQUIRED_DEFINITIONS)
4852
check_symbol_exists(funlockfile "stdio.h"
4953
CSNIP_CONF__HAVE_FUNLOCKFILE)
54+
set(CMAKE_REQUIRED_DEFINITIONS "-D_BSD_SOURCE")
55+
check_symbol_exists(funopen "stdio.h"
56+
CSNIP_CONF__HAVE_FUNOPEN)
57+
unset(CMAKE_REQUIRED_DEFINITIONS)
5058
check_symbol_exists(getc_unlocked "stdio.h"
5159
CSNIP_CONF__HAVE_GETC_UNLOCKED)
5260
check_symbol_exists(getdelim "stdio.h"
@@ -146,6 +154,7 @@ set(c_sources
146154
util.c
147155
x/asprintf.c
148156
x/clock_gettime.c
157+
x/fopencookie.c
149158
x/getdelim.c
150159
x/getline.c
151160
x/getopt.c

src/csnip/csnip_conf.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@
7474
#cmakedefine CSNIP_CONF__HAVE_ASPRINTF
7575
#cmakedefine CSNIP_CONF__HAVE_CLOCK_GETTIME
7676
#cmakedefine CSNIP_CONF__HAVE_FLOCKFILE
77+
#cmakedefine CSNIP_CONF__HAVE_FOPENCOOKIE
7778
#cmakedefine CSNIP_CONF__HAVE_FUNLOCKFILE
79+
#cmakedefine CSNIP_CONF__HAVE_FUNOPEN
7880
#cmakedefine CSNIP_CONF__HAVE_GETC_UNLOCKED
7981
#cmakedefine CSNIP_CONF__HAVE_GETDELIM
8082
#cmakedefine CSNIP_CONF__HAVE_GETLINE

src/csnip/x.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,39 @@ int asprintf(char** strp, const char* fmt, ...);
7878
/** Portable asprintf(). */
7979
int csnip_x_asprintf_imp(char** strp, const char* format, ...);
8080

81+
/** Wrapper for system fopencookie() or funopen(). */
82+
#if defined(CSNIP_CONF__HAVE_FOPENCOOKIE)
83+
typedef cookie_io_functions_t csnip_x_cookie_io_functions_t;
84+
85+
FILE* csnip_x_fopencookie(void* __restrict__ cookie,
86+
const char* __restrict__ mode,
87+
csnip_x_cookie_io_functions_t funcs);
88+
#elif defined(CSNIP_CONF__HAVE_FUNOPEN)
89+
typedef csnip_x_ssize_t csnip_x_cookie_read_function_t(
90+
void* cookie,
91+
char* buf,
92+
size_t size);
93+
typedef csnip_x_ssize_t csnip_x_cookie_write_function_t(
94+
void* cookie,
95+
const char* buf,
96+
size_t size);
97+
typedef int csnip_x_cookie_seek_function_t(
98+
void* cookie,
99+
off_t* offset,
100+
int whence);
101+
typedef int csnip_x_cookie_close_function_t(void* cookie);
102+
typedef struct {
103+
csnip_x_cookie_read_function_t* read;
104+
csnip_x_cookie_write_function_t* write;
105+
csnip_x_cookie_seek_function_t* seek;
106+
csnip_x_cookie_close_function_t* close;
107+
} csnip_x_cookie_io_functions_t;
108+
109+
FILE* csnip_x_fopencookie(void* __restrict__ cookie,
110+
const char* __restrict__ mode,
111+
csnip_x_cookie_io_functions_t funcs);
112+
#endif
113+
81114
/** Wrapper for getdelim or csnip_x_getdelim_imp() */
82115
#define csnip_x_getdelim getdelim
83116
#if !defined(CSNIP_CONF__HAVE_GETDELIM)
@@ -308,13 +341,19 @@ int x_csnip_clock_gettime_imp(csnip_x_clockid_t clk_id,
308341
#ifdef CSNIP_X_CLOCK_MONOTONIC
309342
#define X_CLOCK_MONOTONIC CSNIP_X_CLOCK_MONOTONIC
310343
#endif
344+
#define x_cookie_close_function_t csnip_x_cookie_close_function_t
345+
#define x_cookie_io_functions_t csnip_x_cookie_io_functions_t
346+
#define x_cookie_seek_function_t csnip_x_cookie_seek_function_t
347+
#define x_cookie_read_function_t csnip_x_cookie_read_function_t
348+
#define x_cookie_write_function_t csnip_x_cookie_write_function_t
311349
#define X_CLOCK_REALTIME CSNIP_X_CLOCK_REALTIME
312350
#define x_getdelim csnip_x_getdelim
313351
#define x_getdelim_imp csnip_x_getdelim_imp
314352
#define x_getline csnip_x_getline
315353
#define x_getline_imp csnip_x_getline_imp
316354
#define x_getopt csnip_x_getopt
317355
#define x_getopt_imp csnip_x_getopt_imp
356+
#define x_fopencookie csnip_x_fopencookie
318357
#define x_iovec csnip_x_iovec
319358
#define x_optarg csnip_x_optarg
320359
#define x_optarg_imp csnip_x_optarg_imp

src/csnip/x/fopencookie.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#define _GNU_SOURCE
2+
#define _DEFAULT_SOURCE
3+
4+
#include <errno.h>
5+
6+
#define CSNIP_SHORT_NAMES
7+
#include <csnip/mem.h>
8+
#include <csnip/x.h>
9+
10+
#if defined(CSNIP_CONF__HAVE_FOPENCOOKIE)
11+
FILE* x_fopencookie(void* restrict cookie,
12+
const char* restrict mode,
13+
x_cookie_io_functions_t io_funcs)
14+
{
15+
return fopencookie(cookie, mode, io_funcs);
16+
}
17+
18+
#elif defined(CSNIP_CONF__HAVE_FUNOPEN)
19+
20+
struct cookie_wrapper {
21+
void* cookie;
22+
x_cookie_io_functions_t io_funcs;
23+
};
24+
25+
static int fun_read(void* cw_, char* buf, int sz)
26+
{
27+
struct cookie_wrapper* cw = (struct cookie_wrapper*)cw_;
28+
if (cw->io_funcs.read == NULL) {
29+
/* Signal EOF */
30+
errno = 0;
31+
return 0;
32+
} else {
33+
return (*cw->io_funcs.read)(cw->cookie, buf, sz);
34+
}
35+
}
36+
37+
static int fun_write(void* cw_, const char* buf, int sz)
38+
{
39+
struct cookie_wrapper* cw = (struct cookie_wrapper*)cw_;
40+
if (cw->io_funcs.write == NULL) {
41+
/* Discard data. */
42+
return sz;
43+
} else {
44+
int r = (*cw->io_funcs.write)(cw->cookie, buf, sz);
45+
return (r == 0 ? -1 : r);
46+
}
47+
}
48+
49+
static off_t fun_seek(void* cw_, off_t offs, int whence)
50+
{
51+
struct cookie_wrapper* cw = (struct cookie_wrapper*)cw_;
52+
const int r = (*cw->io_funcs.seek)(cw->cookie, &offs, whence);
53+
if (r == -1)
54+
return -1;
55+
return offs;
56+
}
57+
58+
static int fun_close(void* cw_)
59+
{
60+
struct cookie_wrapper* cw = (struct cookie_wrapper*)cw_;
61+
int r = 0;
62+
if (cw->io_funcs.close != NULL) {
63+
r = (*cw->io_funcs.close)(cw->cookie);
64+
}
65+
mem_Free(cw);
66+
return r;
67+
}
68+
69+
70+
FILE* x_fopencookie(void* restrict cookie,
71+
const char* restrict mode,
72+
x_cookie_io_functions_t io_funcs)
73+
{
74+
/* Create the cookie wrapper */
75+
struct cookie_wrapper* wr;
76+
int err = 0;
77+
mem_Alloc(1, wr, err);
78+
if (err != 0)
79+
return NULL;
80+
*wr = (struct cookie_wrapper){
81+
.cookie = cookie,
82+
.io_funcs = io_funcs,
83+
};
84+
85+
(void)mode;
86+
return funopen(wr,
87+
fun_read,
88+
fun_write,
89+
io_funcs.seek != NULL ? fun_seek : NULL,
90+
fun_close);
91+
92+
}
93+
#endif

0 commit comments

Comments
 (0)