NAME
fmemopen, open_memstream - open memory as stream
SYNOPSIS
#define _GNU_SOURCE
#include <stdio.h>
I FILE *fmemopen(void *buf , size_t size ,
I const char * mode );
I FILE *open_memstream(char ** ptr , size_t * sizeloc )
DESCRIPTION
The
R fmemopen ()
function opens a stream that permits the access specified by
R mode .
The stream allows I/O to be performed on the string or memory buffer
pointed to by
R buf .
This buffer must be at least
size
bytes long.
The argument
mode
is the same as for
fopen(3) .
If
mode
specifies an append mode, then the initial file position is set to
location of the first null byte ('\0') in the buffer;
otherwise the initial file position is set to the start of the buffer.
When a stream that has been opened for writing is flushed
(fflush(3))
or closed
(fclose(3)),
a null byte is written at the end of the buffer if there is space.
The caller should ensure that an extra byte is available in the
buffer
(and that
R size
counts that byte)
to allow for this.
Attempts to write more than
size
bytes to the buffer result in an error.
(By default, such errors will only be visible when the
stdio
buffer is flushed.
Disabling buffering with
setbuf(fp, NULL)
may be useful to detect errors at the time of an output operation.
Alternatively, the caller can explicitly set
buf
as the stdio stream buffer, at the same time informing stdio
of the buffer's size, using
R setbuffer(fp, buf, size) .)
In a stream opened for reading,
null bytes ('\0') in the buffer do not cause read
operations to return an end-of-file indication.
A read from the buffer will only indicate end-of-file
when the file pointer advances
size
bytes past the start of the buffer.
If
buf
is specified as NULL, then
R fmemopen ()
dynamically allocates a buffer
size
bytes long.
This is useful for an application that wants to write data to
a temporary buffer and then read it back again.
The buffer is automatically freed when the stream is closed.
Note that the caller has no way to obtain a pointer to the
temporary buffer allocated by this call (but see
R open_memstream ()
below).
The
R open_memstream ()
opens a stream for writing to a buffer.
The buffer
is dynamically allocated (as with
malloc(3)),
and automatically grows as required.
After closing the stream, the caller should
free(3)
this buffer.
When the stream is closed
(fclose(3))
or flushed
(fflush(3)),
the locations pointed to by
ptr
and
sizeloc
are updated to contain, respectively, a pointer to the buffer and the
current size of the buffer.
These values remain valid only as long as the caller
performs no further output on the stream.
If further output is performed, then the stream
must again be flushed before trying to access these variables.
A null byte is maintained at the end of the buffer.
This byte is
not
included in the size value stored at
R sizeloc .
RETURN VALUE
Upon successful completion
R fmemopen ()
and
R open_memstream ()
return a
FILE
pointer.
Otherwise, NULL is returned and the global variable
errno
is set to indicate the error.
CONFORMING TO
These functions are GNU extensions.
EXAMPLE
The program below uses
R fmemopen ()
to open an input buffer, and
R open_memstream ()
to open a dynamically sized output buffer.
The program scans its input string (taken from the program's
first command-line argument) reading integers,
and writes the squares of these integers to the output buffer.
An example of the output produced by this program is the following:
$ ./a.out "1 23 43"
size=11; ptr=1 529 1849
#define _GNU_SOURCE
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
FILE *out, *in;
int v, s;
size_t size;
char *ptr;
assert(argc == 2);
in = fmemopen(argv[1], strlen(argv[1]), "r");
if (in == NULL)
die("fmemopen");
out = open_memstream(&ptr, &size);
if (out == NULL)
die("fmemopen");
for (;;) {
s = fscanf(in, "%d", &v);
if (s <= 0)
break;
s = fprintf(out, "%d ", v * v);
if (s == -1)
die("fprintf");
}
fclose(in);
fclose(out);
printf("size=%ld; ptr=%s\n", (long) size, ptr);
free(ptr);
exit(EXIT_SUCCESS);
}
SEE ALSO