/*
    PIP - Platform Independent Primitives
    PIIODevice wrapper around PIByteArray
    Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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/>.
*/

#include "piiobytearray.h"


//! \class PIIOByteArray piiobytearray.h
//! \details
//! \~english
//! This class allow you to use PIByteArray as PIIODevice, e.g. to pass it to PIConfig.
//!
//! \~russian
//! Этот класс позволяет использовать PIByteArray в качестве PIIODevice, например,
//! для передачи в PIConfig.
//!


PIIOByteArray::PIIOByteArray(PIByteArray * buffer, PIIODevice::DeviceMode mode) {
	open(buffer, mode);
}


PIIOByteArray::PIIOByteArray(const PIByteArray & buffer) {
	open(buffer);
}


bool PIIOByteArray::open(PIByteArray * buffer, PIIODevice::DeviceMode mode) {
	data_ = buffer;
	mode_ = mode;
	return PIIODevice::open(mode);
}


bool PIIOByteArray::open(const PIByteArray & buffer) {
	data_ = const_cast<PIByteArray *>(&buffer);
	mode_ = PIIODevice::ReadOnly;
	return PIIODevice::open(PIIODevice::ReadOnly);
}


ssize_t PIIOByteArray::readDevice(void * read_to, ssize_t size) {
	// piCout << "PIIOByteArray::read" << data_ << size << canRead();
	if (!canRead() || !data_) return -1;
	int ret = piMini(size, data_->size_s() - pos);
	if (ret <= 0) return -1;
	memcpy(read_to, data_->data(pos), ret);
	// piCout << "readed" << ret;
	pos += ret;
	return ret;
}


ssize_t PIIOByteArray::writeDevice(const void * data, ssize_t size) {
	// piCout << "PIIOByteArray::write" << data << size << canWrite();
	if (!canWrite() || !data) return -1;
	// piCout << "write" << data;
	if (pos > data_->size_s()) pos = data_->size_s();
	PIByteArray rs = PIByteArray(data, size);
	// piCoutObj << rs;
	data_->insert(pos, rs);
	pos += rs.size_s();
	return rs.size_s();
}


int PIIOByteArray::writeByteArray(const PIByteArray & ba) {
	if (!canWrite() || !data_) return -1;
	if (pos > data_->size_s()) pos = data_->size_s();
	data_->insert(pos, ba);
	pos += ba.size_s();
	return ba.size_s();
}


bool PIIOByteArray::openDevice() {
	pos = 0;
	return (data_ != 0);
}
