From eb91fbfc452852a6caec5ee924cc17445e46d5f1 Mon Sep 17 00:00:00 2001 From: peri4 Date: Mon, 1 Aug 2022 21:23:21 +0300 Subject: [PATCH] doc stream --- doc/pages/iostream.md | 117 ++++++++++++++++++++++++++++++ libs/main/core/pibinarystream.h | 8 +- libs/main/core/pibytearray.cpp | 37 ++-------- libs/main/core/pimemoryblock.h | 10 +++ libs/main/core/pitextstream.h | 4 +- libs/main/io_devices/piiostream.h | 2 + main.cpp | 37 ++++------ 7 files changed, 157 insertions(+), 58 deletions(-) create mode 100644 doc/pages/iostream.md diff --git a/doc/pages/iostream.md b/doc/pages/iostream.md new file mode 100644 index 00000000..76b7ebb4 --- /dev/null +++ b/doc/pages/iostream.md @@ -0,0 +1,117 @@ +\~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 +#include + +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 +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 +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 +00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f +0 +0.1 +0.2 +0.3 +0.4 +0.5 +0.6 +0.7 +0.8 +0.9 +\endcode diff --git a/libs/main/core/pibinarystream.h b/libs/main/core/pibinarystream.h index 3fce7a8e..94133e32 100644 --- a/libs/main/core/pibinarystream.h +++ b/libs/main/core/pibinarystream.h @@ -54,8 +54,10 @@ //! bool binaryStreamTakeImp (void * d, size_t s); //! ssize_t binaryStreamSizeImp () const; //! \endcode -//! \~english function binaryStreamSizeImp must return -1 if size unknown -//! \~russian функция binaryStreamSizeImp должна возвращать -1 если нет информации о размере +//! \~english Function binaryStreamSizeImp should return -1 if size unknown. +//! \~russian Функция binaryStreamSizeImp должна возвращать -1 если нет информации о размере. +//! \~english See details \ref iostream. +//! \~russian Подробнее \ref iostream. template class PIBinaryStream { public: @@ -78,7 +80,7 @@ public: //! \~russian Узнать оставшийся размер //!\~\details - //!\~russian возвращает -1 если нет информации о размере + //!\~russian Возвращает -1 если нет информации о размере ssize_t binaryStreamSize() const { return static_cast(this)->binaryStreamSizeImp(); } diff --git a/libs/main/core/pibytearray.cpp b/libs/main/core/pibytearray.cpp index 639a86db..0f950aea 100644 --- a/libs/main/core/pibytearray.cpp +++ b/libs/main/core/pibytearray.cpp @@ -28,6 +28,7 @@ //! It can be constructed from any data and size. //! You can use %PIByteArray as binary stream //! to serialize/deserialize any objects and data. +//! See details \ref iostream. //! This class use PIDeque and provide some handle function //! to manipulate it. //! \~russian @@ -35,46 +36,22 @@ //! Он может быть сконструирован из любых даных. //! Можно использовать %PIByteArray как потоковый объект //! для сериализации/десериализации любых типов и данных. +//! Подробнее \ref iostream. //! Этот класс использует PIDeque и предоставляет набор //! удобных методов для работы с байтами. //! //! \~english \section PIByteArray_sec0 Usage //! \~russian \section PIByteArray_sec0 Использование //! \~english -//! %PIByteArray can be used to store custom data and manipulate it. There are many -//! stream operators to store/restore common types to byte array. Store operators -//! places data at the end of array, restore operators takes data from the beginning +//! %PIByteArray subclass PIBinaryStream and can be used to store custom data and manipulate it. +//! Store operators places data at the end of array, restore operators takes data from the beginning //! of array. -//! In addition there are Hex and Base64 convertions +//! In addition there are Hex and Base64 convertions. //! \~russian -//! %PIByteArray может быть использован для сохранения любых данных и работы с ними. -//! Он предоставляет множество операторов для сохранения/извлечения общих типов. +//! %PIByteArray наследован от PIBinaryStream и может быть использован для сохранения любых данных и работы с ними. //! Операторы сохранения добавляют данные в конец массива, а операторы извлечения //! берут данные из его начала. -//! -//! \~english -//! One of the major usage of %PIByteArray is stream functions. You can form binary -//! packet from many types (also dynamic types, e.g. PIVector) with one line: -//! \~russian -//! Один из основных сценариев использования %PIByteArray - это потоковый объект. -//! Можно сформировать пакет бинарных данных из многих типов (также и контейнеров, -//! например, PIVector) в одну строку: -//! \~\snippet pibytearray.cpp 0 -//! -//! \~english -//! Or you can descibe stream operator of your own type and store/restore vectors of -//! your type: -//! \~russian -//! Также можно описать операторы сохранения/извлечения для собственных типов: -//! \~\snippet pibytearray.cpp 1 -//! -//! \~english -//! For store/restore custom data blocks there is PIByteArray::RawData class. Stream -//! operators of this class simply store/restore data block to/from byte array: -//! \~russian -//! Для сохранения/извлечения блоков произвольных данных используется класс PIByteArray::RawData. -//! Потоковые операторы для него просто сохраняют/извлекают блоки байтов: -//! \~\snippet pibytearray.cpp 2 +//! Также есть методы для преобразования в Hex и Base64. //! //! \~english \section PIByteArray_sec1 Attention //! \~russian \section PIByteArray_sec1 Внимание diff --git a/libs/main/core/pimemoryblock.h b/libs/main/core/pimemoryblock.h index 133d6ae0..e142a679 100644 --- a/libs/main/core/pimemoryblock.h +++ b/libs/main/core/pimemoryblock.h @@ -47,8 +47,16 @@ public: PIMemoryBlock & operator =(const PIMemoryBlock & o) {d = o.d; s = o.s; return *this;} + //! \~english Pointer to data + //! \~russian Указатель на данные void * data() {return d;} + + //! \~english Pointer to data + //! \~russian Указатель на данные const void * data() const {return d;} + + //! \~english Size of data in bytes + //! \~russian Размер данных в байтах int size() const {return s;} private: @@ -57,6 +65,8 @@ private: }; +//! \~english Returns PIMemoryBlock from pointer to variable "ptr" with type "T" +//! \~russian Возвращает PIMemoryBlock из указателя "ptr" типа "T" template PIMemoryBlock createMemoryBlock(const T * ptr) {return PIMemoryBlock(ptr, sizeof(T));} diff --git a/libs/main/core/pitextstream.h b/libs/main/core/pitextstream.h index b4842be2..e0a074cc 100644 --- a/libs/main/core/pitextstream.h +++ b/libs/main/core/pitextstream.h @@ -175,8 +175,8 @@ public: return readUntil(spaces); } - //! \~english - //! \~russian + //! \~english Read C-word, skip leading and until non C-identifier + //! \~russian Читает C-слово, пропуская начальные и до следующих символов, не являющихся C-идентификаторами PIString readCWord() { static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>"); return readUntil(chars); diff --git a/libs/main/io_devices/piiostream.h b/libs/main/io_devices/piiostream.h index 84e62fce..0e23209a 100644 --- a/libs/main/io_devices/piiostream.h +++ b/libs/main/io_devices/piiostream.h @@ -34,6 +34,8 @@ //! \~\brief //! \~english PIBinaryStream functionality for PIIODevice. //! \~russian Функциональность PIBinaryStream для PIIODevice. +//! \~english See details \ref iostream +//! \~russian Подробнее \ref iostream class PIP_EXPORT PIIOBinaryStream: public PIBinaryStream { public: diff --git a/main.cpp b/main.cpp index 56562d12..7125d414 100644 --- a/main.cpp +++ b/main.cpp @@ -1,32 +1,23 @@ #include "pip.h" #include "piiostream.h" +#include "pibytearray.h" using namespace PICoutManipulators; - int main(int argc, char * argv[]) { - { - PIString s("0123456789"); - piCout << s.mid(0, -1); // s = "0123456789" - piCout << s.mid(0, 2); // s = "01" - piCout << s.mid(3, -1); // s = "3456789" - piCout << s.mid(3, 4); // s = "3456" - piCout << s.mid(7, 1); // s = "7" - piCout << s.mid(7, 4); // s = "789" - piCout << s.mid(-1); // s = "" - //! \endcode - //! \~\sa \a left(), \a right() + 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; } - //! \~\details - //! \~\code - PIString s("0123456789"); - s.cutMid(1, 3); - piCout << s; // s = "0456789" - s.cutMid(0, 2); - piCout << s; // s = "56789" - s.cutMid(3, -1); - piCout << s; // s = "567" - s.cutMid(-1, -1); - piCout << s; // s = "567" + 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]; + }