kulp / tenyr
1
#include "stream.h"
2

3
#include <stdarg.h>
4
#include <stdio.h>
5

6 1
static int default_printf(STREAM *s, const char *format, ...)
7
{
8
    // We do not try to be completely general -- if the formatted string will
9
    // not fit in a BUFSIZ, we reserve the right to consider that an error.
10
    // Failing this way is safer than using a variable-length-array and faster
11
    // than allocating from the free store, which means it is better for our
12
    // purposes.
13 1
    char buf[BUFSIZ] = { 0 };
14

15 0
    va_list vl;
16 1
    va_start(vl, format);
17

18 1
    int need = vsnprintf(buf, sizeof buf, format, vl);
19 1
    va_end(vl);
20

21 1
    if (need > 0 && (size_t)need >= sizeof buf)
22 0
        return -1; // we ran out of space
23

24 1
    size_t wrote = s->op.fwrite(buf, 1, (size_t)need, s);
25 1
    return wrote == (size_t)need ? need : -1;
26
}
27

28 1
static int default_scanf(STREAM *s, const char *format, int *word)
29
{
30
    // It is not feasible to defer to op.fread here. We might try to keep a
31
    // buffer of our own to read "enough" to satisfy a vsscanf call, but we
32
    // would not know how many bytes of that buffer were successfully consumed
33
    // unless we could append an "n" specifier to the format and a pointer to
34
    // int to the va_list -- and there is no portable way to append to a
35
    // va_list.
36
    //
37
    // Instead, we simply defer to the system fscanf. This probably prevents a
38
    // library user from reading the text-based formats (which are the only
39
    // ones that want fscanf). Since the text formats are meant basically for
40
    // demonstration and are of increasingly limited use, this is not perceived
41
    // to be a great limitation.
42 1
    return fscanf(s->ud, format, word);
43
}
44

45 1
static size_t default_read(void *ptr, size_t size, size_t nitems, STREAM *s)
46
{
47 1
    return fread(ptr, size, nitems, s->ud);
48
}
49

50 1
static size_t default_write(const void *ptr, size_t size, size_t nitems, STREAM *s)
51
{
52 1
    return fwrite(ptr, size, nitems, s->ud);
53
}
54

55 1
static int default_eof(STREAM *s)
56
{
57 1
    return feof(s->ud);
58
}
59

60 1
static int default_flush(STREAM *s)
61
{
62 1
    return fflush(s->ud);
63
}
64

65 1
static int default_seek(STREAM *s, long offset, int whence)
66
{
67 1
    return fseek(s->ud, offset, whence);
68
}
69

70 1
static long default_tell(STREAM *s)
71
{
72 1
    return ftell(s->ud);
73
}
74

75 1
struct stream_ops stream_get_default_ops(void)
76
{
77 1
    return (struct stream_ops){
78
        .fprintf = default_printf,
79
        .fscanf = default_scanf,
80
        .fread = default_read,
81
        .fwrite = default_write,
82
        .feof = default_eof,
83
        .fflush = default_flush,
84
        .fseek = default_seek,
85
        .ftell = default_tell,
86
    };
87
}
88

89 1
struct stream stream_make_from_file(FILE *f)
90
{
91 1
    return (struct stream){
92
        .ud = f,
93 1
        .op = stream_get_default_ops(),
94
    };
95
}
96

Read our documentation on viewing source code .

Loading