//! \~\file piiostream.h
//! \~\ingroup IO
//! \~\brief
//! \~english Text and binary stream adapters for PIIODevice
//! \~russian Адаптеры текстовых и бинарных потоков для PIIODevice
/*
    PIP - Platform Independent Primitives
    PIBinaryStream functionality for PIIODevice
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIIOSTREAM_H
#define PIIOSTREAM_H

#include "piiostring.h"
#include "pitextstream.h"


//! \~\ingroup IO
//! \~\brief
//! \~english %PIBinaryStream adapter over a \a PIIODevice.
//! \~russian Адаптер %PIBinaryStream поверх \a PIIODevice.
//! \~\details
//! \~english
//! Provides binary stream operations for PIIODevice-based devices.
//! See \ref iostream for the generic stream API.
//! \~russian
//! Предоставляет операции бинарного потока для устройств на основе PIIODevice.
//! Общий API потоков описан в \ref iostream.
class PIP_EXPORT PIIOBinaryStream: public PIBinaryStream<PIIOBinaryStream> {
public:
	//! \~english Constructs a stream bound to "device".
	//! \~russian Создает поток, привязанный к устройству "device".
	PIIOBinaryStream(PIIODevice * device = nullptr): dev(device) {}

	//! \~english Rebinds the stream to "device" and resets read-error state.
	//! \~russian Перепривязывает поток к устройству "device" и сбрасывает состояние ошибки чтения.
	void setDevice(PIIODevice * device) {
		dev = device;
		resetReadError();
	}

	//! \~english Appends raw bytes through the bound device.
	//! \~russian Добавляет сырые байты через привязанное устройство.
	bool binaryStreamAppendImp(const void * d, size_t s) {
		if (!dev) return false;
		return (dev->write(d, s) == (int)s);
	}

	//! \~english Reads raw bytes from the bound device.
	//! \~russian Читает сырые байты из привязанного устройства.
	bool binaryStreamTakeImp(void * d, size_t s) {
		if (!dev) return false;
		return (dev->read(d, s) == (int)s);
	}

	//! \~english Returns the number of bytes currently available in the device.
	//! \~russian Возвращает количество байт, доступных в устройстве в данный момент.
	ssize_t binaryStreamSizeImp() const {
		if (!dev) return 0;
		return dev->bytesAvailable();
	}

private:
	PIIODevice * dev = nullptr;
};


//! \~\ingroup IO
//! \~\brief
//! \~english %PITextStream adapter over a \a PIIODevice.
//! \~russian Адаптер %PITextStream поверх \a PIIODevice.
//! \~\details
//! \~english
//! Provides text stream operations for PIIODevice-based devices.
//! \~russian
//! Предоставляет операции текстового потока для устройств на основе PIIODevice.
class PIP_EXPORT PIIOTextStream: public PITextStream<PIIOBinaryStream> {
public:
	//! \~english Constructs a text stream bound to "device".
	//! \~russian Создает текстовый поток, привязанный к устройству "device".
	PIIOTextStream(PIIODevice * device): PITextStream<PIIOBinaryStream>(&bin_stream), bin_stream(device) {}

	//! \~english Constructs a text stream over "string" using "mode".
	//! \~russian Создает текстовый поток поверх строки "string" с режимом "mode".
	PIIOTextStream(PIString * string, PIIODevice::DeviceMode mode): PITextStream<PIIOBinaryStream>(&bin_stream) {
		io_string = new PIIOString(string, mode);
		bin_stream.setDevice(io_string);
	}

	//! \~english Destroys the stream and owned temporary \a PIIOString, if any.
	//! \~russian Уничтожает поток и временный \a PIIOString, которым он владеет, если он был создан.
	~PIIOTextStream() {
		if (io_string) delete io_string;
	}

	//! \~english Rebinds the text stream to another device.
	//! \~russian Перепривязывает текстовый поток к другому устройству.
	void setDevice(PIIODevice * device) {
		bin_stream = PIIOBinaryStream(device);
		setStream(&bin_stream);
	}

private:
	PIIOString * io_string = nullptr;
	PIIOBinaryStream bin_stream;
};


#endif // PIIOSTREAM_H
