.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 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)