1 /* $NetBSD: fmemopen.c,v 1.8 2012/03/29 14:27:33 christos Exp $ */
4 * Copyright (c)2007, 2010 Takehiko NOZAKI,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 #if defined(LIBC_SCCS) && !defined(lint)
32 __RCSID("$NetBSD: fmemopen.c,v 1.8 2012/03/29 14:27:33 christos Exp $");
33 #endif /* LIBC_SCCS and not lint */
42 #include "reentrant.h"
45 struct fmemopen_cookie
{
46 char *head
, *tail
, *cur
, *eob
;
50 fmemopen_read(void *cookie
, void *buf
, size_t nbytes
)
52 struct fmemopen_cookie
*p
;
55 _DIAGASSERT(cookie
!= NULL
);
56 _DIAGASSERT(buf
!= NULL
&& nbytes
> 0);
58 p
= (struct fmemopen_cookie
*)cookie
;
61 if (p
->cur
== p
->tail
)
64 } while (--nbytes
> 0);
66 return (ssize_t
)(p
->cur
- s
);
70 fmemopen_write(void *cookie
, const void *buf
, size_t nbytes
)
72 struct fmemopen_cookie
*p
;
76 _DIAGASSERT(cookie
!= NULL
);
77 _DIAGASSERT(buf
!= NULL
&& nbytes
> 0);
79 p
= (struct fmemopen_cookie
*)cookie
;
80 if (p
->cur
>= p
->tail
)
84 if (p
->cur
== p
->tail
- 1) {
92 } while (--nbytes
> 0);
98 return (ssize_t
)(p
->cur
- s
);
103 fmemopen_flush(void *cookie
)
105 struct fmemopen_cookie
*p
;
107 _DIAGASSERT(cookie
!= NULL
);
109 p
= (struct fmemopen_cookie
*)cookie
;
110 if (p
->cur
>= p
->tail
)
118 fmemopen_seek(void *cookie
, off_t offset
, int whence
)
120 struct fmemopen_cookie
*p
;
122 _DIAGASSERT(cookie
!= NULL
);
124 p
= (struct fmemopen_cookie
*)cookie
;
129 offset
+= p
->cur
- p
->head
;
132 offset
+= p
->eob
- p
->head
;
138 if (offset
>= (off_t
)0 && offset
<= p
->tail
- p
->head
) {
139 p
->cur
= p
->head
+ (ptrdiff_t)offset
;
140 return (off_t
)(p
->cur
- p
->head
);
147 fmemopen_close0(void *cookie
)
149 _DIAGASSERT(cookie
!= NULL
);
157 fmemopen_close1(void *cookie
)
159 struct fmemopen_cookie
*p
;
161 _DIAGASSERT(cookie
!= NULL
);
163 p
= (struct fmemopen_cookie
*)cookie
;
172 fmemopen(void * __restrict buf
, size_t size
, const char * __restrict mode
)
176 struct fmemopen_cookie
*cookie
;
178 if (size
< (size_t)1)
181 flags
= __sflags(mode
, &oflags
);
185 if ((oflags
& O_RDWR
) == 0 && buf
== NULL
)
193 cookie
= malloc(sizeof(*cookie
));
198 cookie
->head
= malloc(size
);
199 if (cookie
->head
== NULL
) {
203 *cookie
->head
= '\0';
204 fp
->_close
= fmemopen_close1
;
206 cookie
->head
= (char *)buf
;
207 if (oflags
& O_TRUNC
)
208 *cookie
->head
= '\0';
209 fp
->_close
= fmemopen_close0
;
212 cookie
->tail
= cookie
->head
+ size
;
213 cookie
->eob
= cookie
->head
;
215 if (*cookie
->eob
== '\0')
218 } while (--size
> 0);
220 cookie
->cur
= (oflags
& O_APPEND
) ? cookie
->eob
: cookie
->head
;
223 fp
->_write
= (flags
& __SRD
) ? NULL
: fmemopen_write
;
224 fp
->_read
= (flags
& __SWR
) ? NULL
: fmemopen_read
;
225 fp
->_seek
= fmemopen_seek
;
227 fp
->_flush
= fmemopen_flush
;
229 fp
->_cookie
= (void *)cookie
;