* 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:
parent
c6b9747e04
commit
84e851fd64
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue