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
134
135
136
137
138
139
|
.TH MPU_FMEMOPEN 3 "Август 2026" "libmpuio" "Руководство программиста LIBMPUIO"
.SH ИМЯ
mpu_fmemopen, mpu_open_memstream \- потоки памяти UCS-2
.SH ОБЗОР
.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 ОПИСАНИЕ
Эти интерфейсы предоставляют текстовые потоки на основе памяти, использующие
нативное 16-битное представление LIBMPUIO
.BR __mpu_char16_t .
Они намеренно не являются побайтовыми копиями libc fmemopen/open_memstream:
размеры измеряются в кодовых единицах UCS-2, а не в байтах.
.PP
.B mpu_fmemopen
использует хранилище, принадлежащее вызывающей стороне. Аргумент
.I size
задаёт число доступных кодовых единиц
.BR __mpu_char16_t ,
включая место для завершающего NUL при записи. Строгая грамматика режима
r/w/a с необязательными + и b общая с
.BR mpu_fopen (3).
.PP
Для r/r+ начальная логическая длина равна ограниченной длине строки UCS-2,
уже находящейся в буфере. Для w/w+ логическая длина становится равной нулю,
а первая кодовая единица устанавливается в NUL. Для a/a+ начальная позиция
находится на завершающем NUL, а каждая последующая операция вывода добавляет
данные в текущий логический конец, даже если успешный seek изменил текущую
позицию. Успешные текстовые записи поддерживают NUL-терминацию, если это
позволяет ёмкость. Если следующая кодовая единица вместе с завершающим NUL
уже не помещается, вывод завершается с ENOSPC и устанавливает индикатор ошибки
потока, не разрушая существующий завершающий NUL.
.PP
.B mpu_open_memstream
создаёт динамически растущий выходной поток UCS-2, предназначенный только для
записи. Библиотека выделяет и расширяет буфер данных. После
.BR mpu_fflush (3)
(включая форму для всех потоков mpu_fflush(NULL)) либо
.BR mpu_fclose (3),
.I *buffer
указывает на текущий NUL-терминированный выделенный буфер, а
.I *size
содержит логическое число символов UCS-2 без завершающего NUL. После закрытия
опубликованный буфер принадлежит вызывающей стороне и в конечном итоге должен
быть освобождён через
.BR free (3).
.SH МОДЕЛЬ СИМВОЛОВ
Обе функции создают текстовые потоки памяти UCS-2. Преобразование UTF-8 не
выполняется, поскольку внешний байтовый файл отсутствует. Суррогатные кодовые
единицы U+D800..U+DFFF остаются недопустимыми и отвергаются текстовыми
операциями вывода с EILSEQ.
.PP
Сырые байтовые операции
.B mpu_fread/mpu_fwrite
для этих текстовых потоков памяти не определены. Используйте вместо них
символьные, строковые, форматированные или сканирующие интерфейсы.
.SH ПОЗИЦИОНИРОВАНИЕ
Позиции потоков памяти измеряются в кодовых единицах
.BR __mpu_char16_t .
Фиксированный поток
.B mpu_fmemopen
может быть позиционирован в диапазоне от нуля до size-1; последующая запись за
старым логическим концом заполняет промежуточные кодовые единицы NUL и
увеличивает логическую длину. Позиционирование на size или дальше завершается
с EINVAL, поскольку одна кодовая единица должна оставаться доступной для
завершающего NUL.
.PP
Динамический
.B mpu_open_memstream
может быть позиционирован за текущий логический конец. Сам по себе seek не
увеличивает опубликованный размер. Если затем по новой позиции выполняется
запись, промежуток материализуется как кодовые единицы UCS-2 NUL, а логическая
длина увеличивается до вновь записанного символа включительно. Позиционирование
назад с перезаписью существующего содержимого не уменьшает логическую длину.
.PP
Нативные потоки памяти UCS-2 поддерживают то же активное состояние
READING/WRITING, что и потоки на основе дескрипторов и cookie. Успешный seek
сбрасывает EOF и отбрасывает pushback/состояние направления чтения-записи,
согласованно с другими потоками LIBMPUIO.
.BR mpu_fileno (3)
для потоков памяти завершается с EBADF, поскольку у них нет POSIX-дескриптора.
.SH ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Обе функции при успехе возвращают указатель на поток, при ошибке \- NULL.
.SH ОШИБКИ
.B EINVAL
используется для недопустимых указателей, хранилища вызывающей стороны нулевого
размера, недопустимых режимов или операций, несовместимых с текстовым потоком
памяти.
.B ENOSPC
означает, что фиксированный выходной буфер
.B mpu_fmemopen
не способен принять ещё один символ вместе с требуемым NUL.
Ошибки выделения памяти из
.B mpu_open_memstream
сообщаются через обычное поведение errno аллокатора.
.SH ПОТОКОБЕЗОПАСНОСТЬ
Обычные операции над возвращённым потоком используют ту же рекурсивную
блокировку потока, что и остальные потоки LIBMPUIO. Вызывающая сторона не
должна напрямую изменять живой буфер mpu_fmemopen одновременно с потоковыми
операциями. Для mpu_open_memstream опубликованные указатель/размер следует
проверять только после явного flush или после закрытия. Пока поток жив,
realloc может переместить буфер; актуальным является только указатель,
опубликованный последним flush (или окончательным close). После закрытия этот
последний выделенный буфер принадлежит вызывающей стороне и может быть
освобождён через free(3).
.SH ПРИМЕРЫ
Фиксированный поток в памяти вызывающей стороны:
.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 содержит UCS-2 "value=42". */
.fi
.PP
Растущий поток:
.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 NUL-терминирован; length измеряется в элементах __mpu_char16_t. */
mpu_fclose( fp );
free( text );
.fi
.SH СМ. ТАКЖЕ
.BR libmpuio (3),
.BR mpu_fopen (3),
.BR mpu_fgetc (3),
.BR mpu_printf (3),
.BR mpu_scanf (3),
.BR mpu_fseek (3)
|