\~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
