1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
.TH MPU_FMEMOPEN 3 "August 2026" "libmpuio" "LIBMPUIO Programmer's Manual"
.SH NAME
mpu_fmemopen, mpu_open_memstream \- UCS-2 memory streams
.SH SYNOPSIS
.nf
#include <libmpuio.h>
mpu_FILE *mpu_fmemopen( __mpu_char16_t *buffer, size_t size,
const char *mode );
mpu_FILE *mpu_open_memstream( __mpu_char16_t **buffer, size_t *size );
.fi
.SH DESCRIPTION
These interfaces provide memory-backed text streams using LIBMPUIO's native
16-bit
.B __mpu_char16_t
representation. They are deliberately not byte-for-byte clones of libc
fmemopen/open_memstream: sizes are measured in UCS-2 code units, not bytes.
.PP
.B mpu_fmemopen
uses caller-owned storage. The
.I size
argument is the number of
.B __mpu_char16_t
code units available, including space for a trailing NUL when writing. The
strict r/w/a, optional +, optional b mode grammar is shared with
.BR mpu_fopen (3).
.PP
For r/r+ the initial logical length is the bounded UCS-2 string length already
present in the buffer. For w/w+ the logical length becomes zero and the first
code unit is set to NUL. For a/a+ the initial position is the terminating NUL,
and every subsequent output operation appends at the current logical end even
if a successful seek changed the current position. Successful text writes
maintain NUL termination when capacity permits. When no further code unit plus
trailing NUL fits, output fails with ENOSPC and the stream error indicator is
set without destroying the existing terminating NUL.
.PP
.B mpu_open_memstream
creates a dynamically growing output-only UCS-2 stream. The library allocates
and expands the data buffer. After
.BR mpu_fflush (3)
(including the all-stream form mpu_fflush(NULL)) or
.BR mpu_fclose (3),
.I *buffer
points to the current NUL-terminated allocation and
.I *size
contains the logical number of UCS-2 characters, excluding the trailing NUL.
After close, ownership of the published buffer belongs to the caller and it
must eventually be released with
.BR free (3).
.SH CHARACTER MODEL
Both functions are UCS-2 text-memory streams. No UTF-8 conversion occurs
because no external byte file is involved. Surrogate code units U+D800 through
U+DFFF remain invalid and are rejected with EILSEQ by text output operations.
.PP
Raw byte
.B mpu_fread/mpu_fwrite
operations are not defined for these text-memory streams. Use character,
string, formatted, or scanning interfaces instead.
.SH POSITIONING
Memory-stream positions are measured in
.B __mpu_char16_t
code units. A fixed
.B mpu_fmemopen
stream may seek anywhere from zero through size-1; a later write beyond the old
logical end fills the intervening code units with NUL and extends the logical
length. Seeking to size or beyond fails with EINVAL because one code unit must
remain available for the terminating NUL.
.PP
A dynamic
.B mpu_open_memstream
may seek beyond its current logical end. Merely seeking does not increase the
published size. If a later write occurs at the new position, the gap is
materialized as NUL UCS-2 code units and the logical length grows through the
newly written character. Seeking backward and overwriting existing contents
does not shrink the logical length.
.PP
Native UCS-2 memory streams maintain the same active READING/WRITING state
as descriptor and cookie streams. A successful seek clears EOF and discards
pushback/read-write direction state, consistent with other LIBMPUIO streams.
.BR mpu_fileno (3)
fails with EBADF for memory streams because they have no POSIX descriptor.
.SH RETURN VALUE
Both functions return a stream pointer on success and NULL on failure.
.SH ERRORS
.B EINVAL
is used for invalid pointers, zero-size caller-owned storage, invalid modes,
or operations incompatible with a text-memory stream.
.B ENOSPC
indicates a fixed
.B mpu_fmemopen
output buffer that cannot accept another character plus its required NUL.
Allocation failures from
.B mpu_open_memstream
are reported through the usual allocator errno behavior.
.SH THREAD SAFETY
Ordinary operations on the returned stream use the same recursive stream lock
as other LIBMPUIO streams. The caller must not directly alter a live
mpu_fmemopen buffer concurrently with stream operations. For
mpu_open_memstream, inspect the published pointer/size only after an explicit
flush or after close. Reallocation may move the buffer while the stream is
live; only the pointer published by the most recent flush (or final close) is
current. After close, that final allocation belongs to the caller and may be
released with free(3).
.SH EXAMPLES
A fixed caller-owned stream:
.nf
__mpu_char16_t storage[128];
mpu_FILE *fp = mpu_fmemopen( storage, 128, "w+" );
mpu_fprintf( fp, MPU_UCS2("value=%d"), 42 );
mpu_fflush( fp );
/* storage now contains UCS-2 "value=42". */
.fi
.PP
A growing stream:
.nf
__mpu_char16_t *text = NULL;
size_t length = 0;
mpu_FILE *fp = mpu_open_memstream( &text, &length );
mpu_fprintf( fp, MPU_UCS2("name=%s"), MPU_UCS2("mpu") );
mpu_fflush( fp );
/* text is NUL terminated; length is in __mpu_char16_t units. */
mpu_fclose( fp );
free( text );
.fi
.SH SEE ALSO
.BR libmpuio (3),
.BR mpu_fopen (3),
.BR mpu_fgetc (3),
.BR mpu_printf (3),
.BR mpu_scanf (3),
.BR mpu_fseek (3)
|