126 lines
4.0 KiB
Markdown
126 lines
4.0 KiB
Markdown
\~english \page iostream Input/Output stream
|
||
\~russian \page iostream Поток ввода/вывода
|
||
|
||
\~english
|
||
|
||
\~russian
|
||
%PIBinaryStream представляет собой интерфейс бинарной сериализации.
|
||
Не может быть использован в чистом виде, только в виде миксина или
|
||
готовых классов: PIByteArray и PIIOBinaryStream.
|
||
|
||
|
||
Используется для сохранения или чтения любых данных. Простые типы читаются/пишутся
|
||
как блоки памяти, если не созданы конкретные операторы. Сложные типы
|
||
([нетривиальные](https://ru.cppreference.com/w/cpp/types/is_trivially_copyable))
|
||
обязаны иметь операторы ввода/вывода, иначе возникнет ошибка компиляции.
|
||
|
||
Также поддерживаются контейнеры с типами по таким же правилам.
|
||
|
||
Перечисления интерпретируются как int, логические типы как один байт.
|
||
|
||
Операторы сохранения добавляют данные в конец потока, а операторы извлечения
|
||
берут данные из его начала.
|
||
|
||
Для облегчения написания операторов есть макросы:
|
||
* BINARY_STREAM_FRIEND(T) - объявить операторы с доступом к приватному
|
||
содержимому типа T, необязателен;
|
||
* BINARY_STREAM_WRITE(T) - запись в поток, "s" - объект потока, "v" - объект типа T;
|
||
* BINARY_STREAM_READ(T) - чтение из потока, "s" - объект потока, "v" - объект типа T.
|
||
|
||
Пример:
|
||
\~\code{.cpp}
|
||
#include <pibytearray.h>
|
||
|
||
class MyType {
|
||
BINARY_STREAM_FRIEND(MyType);
|
||
public:
|
||
|
||
void setInt(int v) {m_i = v;}
|
||
int getInt() const {return m_i;}
|
||
|
||
void setString(PIString v) {m_s = v;}
|
||
PIString getString() const {return m_s;}
|
||
|
||
private:
|
||
int m_i = 0;
|
||
PIString m_s;
|
||
|
||
};
|
||
|
||
BINARY_STREAM_WRITE(MyType) {s << v.m_i << v.m_s; return s;}
|
||
BINARY_STREAM_READ (MyType) {s >> v.m_i >> v.m_s; return s;}
|
||
|
||
int main(int argc, char * argv[]) {
|
||
MyType t_read, t_write;
|
||
t_write.setInt(10);
|
||
t_write.setString("text");
|
||
|
||
PIByteArray data;
|
||
data << t_write;
|
||
|
||
piCout << data.toHex();
|
||
|
||
data >> t_read;
|
||
piCout << t_read.getInt() << t_read.getString();
|
||
|
||
piCout << data.toHex();
|
||
}
|
||
\endcode
|
||
|
||
\~english Result:
|
||
\~russian Результат:
|
||
\~\code{.cpp}
|
||
0a000000040000007400650078007400
|
||
10 text
|
||
|
||
\endcode
|
||
|
||
|
||
\~english
|
||
For store/restore custom data blocks this is PIMemoryBlock class. Stream
|
||
operators of this class simply store/restore data block to/from stream:
|
||
|
||
\~russian
|
||
Для сохранения/извлечения блоков произвольных данных используется класс PIMemoryBlock.
|
||
Потоковые операторы для него просто сохраняют/извлекают блоки байтов в/из потока:
|
||
|
||
\~\code{.cpp}
|
||
float a_read[10], a_write[10];
|
||
for (int i = 0; i < 10; ++i) {
|
||
a_read [i] = 0.f;
|
||
a_write[i] = i / 10.f;
|
||
}
|
||
|
||
PIByteArray data;
|
||
data << PIMemoryBlock(a_write, 10 * sizeof(float));
|
||
|
||
piCout << data.toHex();
|
||
|
||
data >> PIMemoryBlock(a_read, 10 * sizeof(float));
|
||
for (int i = 0; i < 10; ++i)
|
||
piCout << a_read[i];
|
||
\endcode
|
||
|
||
\~english Result:
|
||
\~russian Результат:
|
||
\~\code{.cpp}
|
||
00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f
|
||
0
|
||
0.1
|
||
0.2
|
||
0.3
|
||
0.4
|
||
0.5
|
||
0.6
|
||
0.7
|
||
0.8
|
||
0.9
|
||
\endcode
|
||
|
||
\~english
|
||
|
||
\~russian
|
||
Если при чтении из потока не хватило данных (например, закончился массив или файл), то проверка
|
||
объекта потока на wasReadError() вернёт true. Рекомендуется делать эту проверку после чтения
|
||
данных для корректной обработки ошибки.
|