Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_fopen_smem.c @ master

History | View | Annotate | Download (3.39 KB)

1
/* vim: set ai sw=8 sts=8 ts=8 :*/
2

    
3
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9
**        All rights reserved.
10
**
11
**        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
**
17
**        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
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        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
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30

    
31
/*
32
**  Open up a stream backed by (static) memory.
33
**
34
**        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
*/
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
#   define _GNU_SOURCE        1        // required to get fopencookie
46
#else
47
#   error Cannot determine use of funopen vs fopencookie
48
#endif
49

    
50
#include <ep.h>
51
#include <string.h>
52
#include <stdio.h>
53
#include <sys/errno.h>
54

    
55
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
        struct meminfo *minf = (struct meminfo *) cookie;
66
        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
        struct meminfo *minf = (struct meminfo *) cookie;
80
        size_t l = minf->bufs - minf->bufx;
81

    
82
        if (l > size)
83
                l = size;
84
        if (l < size)
85
                errno = ENOSPC;
86
        if (l > 0)
87
        {
88
                memcpy(minf->bufb + minf->bufx, buf, l);
89
                minf->bufx += l;
90
                return l;
91
        }
92
        else
93
        {
94
                return -1;
95
        }
96
}
97

    
98
static int
99
memclose(void *cookie)
100
{
101
        struct meminfo *minf = (struct meminfo *) cookie;
102

    
103
        if (minf->bufs > minf->bufx)
104
                minf->bufb[minf->bufx] = '\0';
105
        ep_mem_free(cookie);
106
        return 0;
107
}
108

    
109

    
110
FILE *
111
ep_fopen_smem(void *buf,
112
        size_t size,
113
        const char *mode)
114
{
115
        struct meminfo *minf = (struct meminfo *) ep_mem_zalloc(sizeof *minf);
116
        if (minf == NULL)
117
                return NULL;
118
        minf->bufb = (char *) buf;
119
        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
}