1 /* $NetBSD: fmemopen.c,v 1.5 2010/09/27 17:08:29 tnozaki 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.5 2010/09/27 17:08:29 tnozaki 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
, char *buf
, int 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 (int)(p
->cur
- s
);
70 fmemopen_write(void *cookie
, const char *buf
, int nbytes
)
72 struct fmemopen_cookie
*p
;
75 _DIAGASSERT(cookie
!= NULL
);
76 _DIAGASSERT(buf
!= NULL
&& nbytes
> 0);
78 p
= (struct fmemopen_cookie
*)cookie
;
79 if (p
->cur
>= p
->tail
)
83 if (p
->cur
== p
->tail
- 1) {
91 } while (--nbytes
> 0);
97 return (int)(p
->cur
- s
);
101 fmemopen_seek(void *cookie
, fpos_t offset
, int whence
)
103 struct fmemopen_cookie
*p
;
105 _DIAGASSERT(cookie
!= NULL
);
107 p
= (struct fmemopen_cookie
*)cookie
;
112 offset
+= p
->cur
- p
->head
;
115 offset
+= p
->eob
- p
->head
;
121 if (offset
>= (fpos_t)0 && offset
<= p
->tail
- p
->head
) {
122 p
->cur
= p
->head
+ (ptrdiff_t)offset
;
123 return (fpos_t)(p
->cur
- p
->head
);
130 fmemopen_close0(void *cookie
)
132 _DIAGASSERT(cookie
!= NULL
);
140 fmemopen_close1(void *cookie
)
142 struct fmemopen_cookie
*p
;
144 _DIAGASSERT(cookie
!= NULL
);
146 p
= (struct fmemopen_cookie
*)cookie
;
155 fmemopen(void * __restrict buf
, size_t size
, const char * __restrict mode
)
159 struct fmemopen_cookie
*cookie
;
161 if (size
< (size_t)1)
164 flags
= __sflags(mode
, &oflags
);
168 if ((oflags
& O_RDWR
) == 0 && buf
== NULL
)
176 cookie
= malloc(sizeof(*cookie
));
181 cookie
->head
= malloc(size
);
182 if (cookie
->head
== NULL
) {
186 *cookie
->head
= '\0';
187 fp
->_close
= &fmemopen_close1
;
189 cookie
->head
= (char *)buf
;
190 if (oflags
& O_TRUNC
)
191 *cookie
->head
= '\0';
192 fp
->_close
= &fmemopen_close0
;
195 cookie
->tail
= cookie
->head
+ size
;
196 cookie
->eob
= cookie
->head
;
198 if (*cookie
->eob
== '\0')
201 } while (--size
> 0);
203 cookie
->cur
= (oflags
& O_APPEND
) ? cookie
->eob
: cookie
->head
;
206 fp
->_write
= (flags
& __SRD
) ? NULL
: &fmemopen_write
;
207 fp
->_read
= (flags
& __SWR
) ? NULL
: &fmemopen_read
;
208 fp
->_seek
= &fmemopen_seek
;
209 fp
->_cookie
= (void *)cookie
;