* libc/stdio/open_memstream.c: Add open_wmemstream to doumentation.

(struct memstream): Add wide element.
	Change saved to a union to take char and wchar_t values.
	(memwriter): Accommodate wide-oriented oeprations.
	(memseeker): Ditto.
	(memseeker64): Ditto.
	(memcloser): Ditto.
	(internal_open_memstream_r): New static function.  Take functionality
	from former _open_memstream_r and handle additional "wide" parameter.
	(_open_memstream_r): Just call internal_open_memstream_r with wide==-1
	from here.
	(_open_wmemstream_r): New function.
	(open_wmemstream): Ditto.
	* libc/include/wchar.h (open_wmemstream): Declare.
	(_open_wmemstream_r): Declare.
This commit is contained in:
Corinna Vinschen 2009-02-18 17:35:24 +00:00
parent c6b9747e04
commit 84e851fd64
3 changed files with 123 additions and 26 deletions

View File

@ -1,3 +1,21 @@
2009-02-18 Corinna Vinschen <corinna@vinschen.de>
* libc/stdio/open_memstream.c: Add open_wmemstream to doumentation.
(struct memstream): Add wide element.
Change saved to a union to take char and wchar_t values.
(memwriter): Accommodate wide-oriented oeprations.
(memseeker): Ditto.
(memseeker64): Ditto.
(memcloser): Ditto.
(internal_open_memstream_r): New static function. Take functionality
from former _open_memstream_r and handle additional "wide" parameter.
(_open_memstream_r): Just call internal_open_memstream_r with wide==-1
from here.
(_open_wmemstream_r): New function.
(open_wmemstream): Ditto.
* libc/include/wchar.h (open_wmemstream): Declare.
(_open_wmemstream_r): Declare.
2009-02-16 Corinna Vinschen <corinna@vinschen.de> 2009-02-16 Corinna Vinschen <corinna@vinschen.de>
* libc/stdio/fputwc.c: Fix typo in man page info. * libc/stdio/fputwc.c: Fix typo in man page info.

View File

@ -118,6 +118,9 @@ wint_t _EXFUN(_putwc_r, (struct _reent *, wchar_t, __FILE *));
wint_t _EXFUN(_putwchar_r, (struct _reent *, wchar_t)); wint_t _EXFUN(_putwchar_r, (struct _reent *, wchar_t));
wint_t _EXFUN (_ungetwc_r, (struct _reent *, wint_t wc, __FILE *)); wint_t _EXFUN (_ungetwc_r, (struct _reent *, wint_t wc, __FILE *));
__FILE *_EXFUN (open_wmemstream, (wchar_t **, size_t *));
__FILE *_EXFUN (_open_wmemstream_r, (struct _reent *, wchar_t **, size_t *));
#define getwc(fp) fgetwc(fp) #define getwc(fp) fgetwc(fp)
#define putwc(wc,fp) fputwc((wc), (fp)) #define putwc(wc,fp) fputwc((wc), (fp))
#ifndef _REENT_ONLY #ifndef _REENT_ONLY

View File

@ -5,19 +5,25 @@
/* /*
FUNCTION FUNCTION
<<open_memstream>>---open a write stream around an arbitrary-length string <<open_memstream>>, <<open_wmemstream>>---open a write stream around an arbitrary-length string
INDEX INDEX
open_memstream open_memstream
INDEX
open_wmemstream
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdio.h> #include <stdio.h>
FILE *open_memstream(char **restrict <[buf]>, FILE *open_memstream(char **restrict <[buf]>,
size_t *restrict <[size]>); size_t *restrict <[size]>);
#include <wchar.h>
FILE *open_wmemstream(wchar_t **restrict <[buf]>,
size_t *restrict <[size]>);
DESCRIPTION DESCRIPTION
<<open_memstream>> creates a seekable <<FILE>> stream that wraps an <<open_memstream>> creates a seekable, byte-oriented <<FILE>> stream that
arbitrary-length buffer, created as if by <<malloc>>. The current wraps an arbitrary-length buffer, created as if by <<malloc>>. The current
contents of *<[buf]> are ignored; this implementation uses *<[size]> contents of *<[buf]> are ignored; this implementation uses *<[size]>
as a hint of the maximum size expected, but does not fail if the hint as a hint of the maximum size expected, but does not fail if the hint
was wrong. The parameters <[buf]> and <[size]> are later stored was wrong. The parameters <[buf]> and <[size]> are later stored
@ -27,6 +33,10 @@ after fflush, the pointer is only valid until another stream operation
that results in a write. Behavior is undefined if the user alters that results in a write. Behavior is undefined if the user alters
either *<[buf]> or *<[size]> prior to <<fclose>>. either *<[buf]> or *<[size]> prior to <<fclose>>.
<<open_wmemstream>> is like <<open_memstream>> just with the associated
stream being wide-oriented. The size set in <[size]> in subsequent
operations is the number of wide characters.
The stream is write-only, since the user can directly read *<[buf]> The stream is write-only, since the user can directly read *<[buf]>
after a flush; see <<fmemopen>> for a way to wrap a string with a after a flush; see <<fmemopen>> for a way to wrap a string with a
readable stream. The user is responsible for calling <<free>> on readable stream. The user is responsible for calling <<free>> on
@ -34,10 +44,10 @@ the final *<[buf]> after <<fclose>>.
Any time the stream is flushed, a NUL byte is written at the current Any time the stream is flushed, a NUL byte is written at the current
position (but is not counted in the buffer length), so that the string position (but is not counted in the buffer length), so that the string
is always NUL-terminated after at most *<[size]> bytes. However, data is always NUL-terminated after at most *<[size]> bytes (or wide characters
previously written beyond the current stream offset is not lost, and in case of <<open_wmemstream>>). However, data previously written beyond
the NUL byte written during a flush is restored to its previous value the current stream offset is not lost, and the NUL value written during a
when seeking elsewhere in the string. flush is restored to its previous value when seeking elsewhere in the string.
RETURNS RETURNS
The return value is an open FILE pointer on success. On error, The return value is an open FILE pointer on success. On error,
@ -46,12 +56,13 @@ or <[size]> is NULL, ENOMEM if memory could not be allocated, or
EMFILE if too many streams are already open. EMFILE if too many streams are already open.
PORTABILITY PORTABILITY
This function is being added to POSIX 200x, but is not in POSIX 2001. POSIX.1-2008
Supporting OS subroutines required: <<sbrk>>. Supporting OS subroutines required: <<sbrk>>.
*/ */
#include <stdio.h> #include <stdio.h>
#include <wchar.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <sys/lock.h> #include <sys/lock.h>
@ -71,7 +82,11 @@ typedef struct memstream {
size_t pos; /* current position */ size_t pos; /* current position */
size_t eof; /* current file size */ size_t eof; /* current file size */
size_t max; /* current malloc buffer size, always > eof */ size_t max; /* current malloc buffer size, always > eof */
char saved; /* saved character that lived at *psize before NUL */ union {
char c;
wchar_t w;
} saved; /* saved character that lived at *psize before NUL */
int8_t wide; /* wide-oriented (>0) or byte-oriented (<0) */
} memstream; } memstream;
/* Write up to non-zero N bytes of BUF into the stream described by COOKIE, /* Write up to non-zero N bytes of BUF into the stream described by COOKIE,
@ -119,10 +134,12 @@ _DEFUN(memwriter, (ptr, cookie, buf, n),
trailing NUL is overwriting. Otherwise, extend the stream. */ trailing NUL is overwriting. Otherwise, extend the stream. */
if (c->pos > c->eof) if (c->pos > c->eof)
c->eof = c->pos; c->eof = c->pos;
else if (c->wide > 0)
c->saved.w = *(wchar_t *)(cbuf + c->pos);
else else
c->saved = cbuf[c->pos]; c->saved.c = cbuf[c->pos];
cbuf[c->pos] = '\0'; cbuf[c->pos] = '\0';
*c->psize = c->pos; *c->psize = (c->wide > 0) ? c->pos / sizeof (wchar_t) : c->pos;
return n; return n;
} }
@ -163,16 +180,30 @@ _DEFUN(memseeker, (ptr, cookie, pos, whence),
{ {
if (c->pos < c->eof) if (c->pos < c->eof)
{ {
(*c->pbuf)[c->pos] = c->saved; if (c->wide > 0)
c->saved = '\0'; *(wchar_t *)((*c->pbuf) + c->pos) = c->saved.w;
else
(*c->pbuf)[c->pos] = c->saved.c;
c->saved.w = L'\0';
} }
c->pos = offset; c->pos = offset;
if (c->pos < c->eof) if (c->pos < c->eof)
{ {
c->saved = (*c->pbuf)[c->pos]; if (c->wide > 0)
(*c->pbuf)[c->pos] = '\0'; {
*c->psize = c->pos; c->saved.w = *(wchar_t *)((*c->pbuf) + c->pos);
*(wchar_t *)((*c->pbuf) + c->pos) = L'\0';
*c->psize = c->pos / sizeof (wchar_t);
}
else
{
c->saved.c = (*c->pbuf)[c->pos];
(*c->pbuf)[c->pos] = '\0';
*c->psize = c->pos;
}
} }
else if (c->wide > 0)
*c->psize = c->eof / sizeof (wchar_t);
else else
*c->psize = c->eof; *c->psize = c->eof;
} }
@ -210,16 +241,30 @@ _DEFUN(memseeker64, (ptr, cookie, pos, whence),
{ {
if (c->pos < c->eof) if (c->pos < c->eof)
{ {
(*c->pbuf)[c->pos] = c->saved; if (c->wide > 0)
c->saved = '\0'; *(wchar_t *)((*c->pbuf) + c->pos) = c->saved.w;
else
(*c->pbuf)[c->pos] = c->saved.c;
c->saved.w = L'\0';
} }
c->pos = offset; c->pos = offset;
if (c->pos < c->eof) if (c->pos < c->eof)
{ {
c->saved = (*c->pbuf)[c->pos]; if (c->wide > 0)
(*c->pbuf)[c->pos] = '\0'; {
*c->psize = c->pos; c->saved.w = *(wchar_t *)((*c->pbuf) + c->pos);
*(wchar_t *)((*c->pbuf) + c->pos) = L'\0';
*c->psize = c->pos / sizeof (wchar_t);
}
else
{
c->saved.c = (*c->pbuf)[c->pos];
(*c->pbuf)[c->pos] = '\0';
*c->psize = c->pos;
}
} }
else if (c->wide > 0)
*c->psize = c->eof / sizeof (wchar_t);
else else
*c->psize = c->eof; *c->psize = c->eof;
} }
@ -237,7 +282,9 @@ _DEFUN(memcloser, (ptr, cookie),
char *buf; char *buf;
/* Be nice and try to reduce any unused memory. */ /* Be nice and try to reduce any unused memory. */
buf = _realloc_r (ptr, *c->pbuf, *c->psize + 1); buf = _realloc_r (ptr, *c->pbuf,
c->wide > 0 ? (*c->psize + 1) * sizeof (wchar_t)
: *c->psize + 1);
if (buf) if (buf)
*c->pbuf = buf; *c->pbuf = buf;
_free_r (ptr, c->storage); _free_r (ptr, c->storage);
@ -246,11 +293,12 @@ _DEFUN(memcloser, (ptr, cookie),
/* Open a memstream that tracks a dynamic buffer in BUF and SIZE. /* Open a memstream that tracks a dynamic buffer in BUF and SIZE.
Return the new stream, or fail with NULL. */ Return the new stream, or fail with NULL. */
FILE * static FILE *
_DEFUN(_open_memstream_r, (ptr, buf, size), _DEFUN(internal_open_memstream_r, (ptr, buf, size, wide),
struct _reent *ptr _AND struct _reent *ptr _AND
char **buf _AND char **buf _AND
size_t *size) size_t *size _AND
int wide)
{ {
FILE *fp; FILE *fp;
memstream *c; memstream *c;
@ -300,7 +348,8 @@ _DEFUN(_open_memstream_r, (ptr, buf, size),
c->pbuf = buf; c->pbuf = buf;
c->psize = size; c->psize = size;
c->eof = 0; c->eof = 0;
c->saved = '\0'; c->saved.w = L'\0';
c->wide = (int8_t) wide;
_flockfile (fp); _flockfile (fp);
fp->_file = -1; fp->_file = -1;
@ -314,10 +363,29 @@ _DEFUN(_open_memstream_r, (ptr, buf, size),
fp->_flags |= __SL64; fp->_flags |= __SL64;
#endif #endif
fp->_close = memcloser; fp->_close = memcloser;
ORIENT (fp, wide);
_funlockfile (fp); _funlockfile (fp);
return fp; return fp;
} }
FILE *
_DEFUN(_open_memstream_r, (ptr, buf, size),
struct _reent *ptr _AND
char **buf _AND
size_t *size)
{
internal_open_memstream_r (ptr, buf, size, -1);
}
FILE *
_DEFUN(_open_wmemstream_r, (ptr, buf, size),
struct _reent *ptr _AND
wchar_t **buf _AND
size_t *size)
{
internal_open_memstream_r (ptr, buf, size, 1);
}
#ifndef _REENT_ONLY #ifndef _REENT_ONLY
FILE * FILE *
_DEFUN(open_memstream, (buf, size), _DEFUN(open_memstream, (buf, size),
@ -326,4 +394,12 @@ _DEFUN(open_memstream, (buf, size),
{ {
return _open_memstream_r (_REENT, buf, size); return _open_memstream_r (_REENT, buf, size);
} }
FILE *
_DEFUN(open_wmemstream, (buf, size),
wchar_t **buf _AND
size_t *size)
{
return _open_wmemstream_r (_REENT, buf, size);
}
#endif /* !_REENT_ONLY */ #endif /* !_REENT_ONLY */