Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_fopen_smem.c @ master

History | View | Annotate | Download (3.39 KB)

1 a901db09 Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 :*/
2 47c6ea64 Eric Allman
3 055d3009 Eric Allman
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7 c87dd166 Eric Allman
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9 6bd5476b Eric Allman
**        All rights reserved.
10 055d3009 Eric Allman
**
11 6bd5476b Eric Allman
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16 055d3009 Eric Allman
**
17 6bd5476b Eric Allman
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 055d3009 Eric Allman
**
22 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 6bd5476b Eric Allman
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28 055d3009 Eric Allman
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30
31 47c6ea64 Eric Allman
/*
32 6c7e8d27 Eric Allman
**  Open up a stream backed by (static) memory.
33 47c6ea64 Eric Allman
**
34 14aa795e Eric Allman
**        This is a wrapper around funopen (on BSD and MacOS) or
35
**        fopencookie (on Linux).  These two routimes do substantially
36
**        the same thing.
37 47c6ea64 Eric Allman
*/
38
39
#if __FreeBSD__ || __APPLE__
40
#   define IORESULT_T        int
41
#   define IOBLOCK_T        int
42
#elif __linux__
43
#   define IORESULT_T        ssize_t
44
#   define IOBLOCK_T        size_t
45 cd4cc511 Eric Allman
#   define _GNU_SOURCE        1        // required to get fopencookie
46 47c6ea64 Eric Allman
#else
47
#   error Cannot determine use of funopen vs fopencookie
48
#endif
49
50 cd4cc511 Eric Allman
#include <ep.h>
51
#include <string.h>
52
#include <stdio.h>
53
#include <sys/errno.h>
54
55 47c6ea64 Eric Allman
struct meminfo
56
{
57
        char *bufb;                // base of buffer
58
        size_t bufs;                // size of buffer
59
        size_t bufx;                // index of current read/write pointer
60
};
61
62
static IORESULT_T
63
memread(void *cookie, char *buf, IOBLOCK_T size)
64
{
65 fc0cbc23 Eric Allman
        struct meminfo *minf = (struct meminfo *) cookie;
66 47c6ea64 Eric Allman
        size_t l = minf->bufs - minf->bufx;
67
68
        if (l > size)
69
                l = size;
70
        if (l > 0)
71
                memcpy(buf, minf->bufb + minf->bufx, l);
72
        minf->bufx += l;
73
        return l;
74
}
75
76
static IORESULT_T
77
memwrite(void *cookie, const char *buf, IOBLOCK_T size)
78
{
79 fc0cbc23 Eric Allman
        struct meminfo *minf = (struct meminfo *) cookie;
80 328ab6a8 Eric Allman
        size_t l = minf->bufs - minf->bufx;
81 47c6ea64 Eric Allman
82
        if (l > size)
83
                l = size;
84 6fa02291 Eric Allman
        if (l < size)
85
                errno = ENOSPC;
86 47c6ea64 Eric Allman
        if (l > 0)
87 6fa02291 Eric Allman
        {
88 47c6ea64 Eric Allman
                memcpy(minf->bufb + minf->bufx, buf, l);
89 6fa02291 Eric Allman
                minf->bufx += l;
90 328ab6a8 Eric Allman
                return l;
91 6fa02291 Eric Allman
        }
92
        else
93 328ab6a8 Eric Allman
        {
94
                return -1;
95
        }
96 47c6ea64 Eric Allman
}
97
98
static int
99
memclose(void *cookie)
100
{
101 fc0cbc23 Eric Allman
        struct meminfo *minf = (struct meminfo *) cookie;
102 11866981 Eric Allman
103
        if (minf->bufs > minf->bufx)
104
                minf->bufb[minf->bufx] = '\0';
105 47c6ea64 Eric Allman
        ep_mem_free(cookie);
106
        return 0;
107
}
108
109
110
FILE *
111 a5a912e2 Eric Allman
ep_fopen_smem(void *buf,
112 47c6ea64 Eric Allman
        size_t size,
113
        const char *mode)
114
{
115 fc0cbc23 Eric Allman
        struct meminfo *minf = (struct meminfo *) ep_mem_zalloc(sizeof *minf);
116 47c6ea64 Eric Allman
        if (minf == NULL)
117
                return NULL;
118 fc0cbc23 Eric Allman
        minf->bufb = (char *) buf;
119 47c6ea64 Eric Allman
        minf->bufs = size;
120
        minf->bufx = 0;
121
122
#if __FreeBSD__ || __APPLE__
123
        {
124
                // BSD/MacOS
125
                return funopen(minf, &memread, &memwrite, NULL, &memclose);
126
        }
127
#elif __linux__
128
        {
129
                // Linux
130
                cookie_io_functions_t iof =
131
                {
132
                        &memread,
133
                        &memwrite,
134
                        NULL,
135
                        &memclose
136
                };
137
                return fopencookie(minf, mode, iof);
138
        }
139
#endif
140
}