/*
 *
 *
 *    device.cc
 *
 *    C++ source code for class my::iocore member functions and/or static
 *    member data.
 *
 *    =========================================================================
 *
 *    Copyright (C) 2003 by Matt Roberts, KK5JY.
 *
 *    This library 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 2.1 of the License, or (at your option) any later version.
 *
 *    This library 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 library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    =========================================================================
 *
 *
 */


#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

#include <my++/device.h>

//#include <iostream>
//using namespace std;

/*
 *
 *   buffer routines
 *
 */

bool my::device::setbuf (size_t len) {
	if (d_buffer)
		delete [] d_buffer;

	d_buffer = NULL;
	d_buflen = 0;

	if (len) {
		d_buffer = new unsigned char[len];
		if (d_buffer == NULL)
			return false;
		d_buflen = len;
	}

	return true;
}

unsigned char * my::device::buffer (void) {
	if (!d_buffer)
		setbuf();
	return d_buffer;
}

size_t my::device::buflen (void) {
	if (!d_buffer)
		setbuf();
	return d_buflen;
}

my::device::~device (void) throw() {
	setbuf(0);
}

my::device::device (void) throw() : d_buffer(NULL), d_buflen(0) {
	/* noop */
}


/*
 *
 *   I/O routines
 *
 */

size_t my::idevice::get (void *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// read from the device
	ssize_t count = read_vp ((void*)buf, len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::idevice::get (char *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// read from the device
	ssize_t count = read_vp ((void*)(buf), len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::idevice::get (unsigned char *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// read from the device
	ssize_t count = read_vp ((void*)(buf), len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::idevice::get (std::string &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	ssize_t count = read_vp ((void*)buffer(), buflen());

	if (count < 0)
		throw device::exception(this, errno);

	buf.insert(buf.end(), (char*)buffer(), (char*)buffer() + count);

	return count;
}

size_t my::idevice::get (std::deque<unsigned char> &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	ssize_t count = read_vp ((void*)buffer(), buflen());

	if (count < 0)
		throw device::exception(this, errno);

	buf.insert(buf.end(), buffer(), buffer() + count);

	return count;
}

size_t my::idevice::get (std::deque<char> &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	ssize_t count = read_vp ((void*)buffer(), buflen());

	if (count < 0)
		throw device::exception(this, errno);

	buf.insert(buf.end(), buffer(), buffer() + count);

	return count;
}

size_t my::odevice::put (const void *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// write to the device
	ssize_t count = write_vp ((void*)buf, len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::odevice::put (const char *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// write to the device
	ssize_t count = write_vp ((void*)(buf), len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::odevice::put (const unsigned char *buf, size_t len) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	// write to the device
	ssize_t count = write_vp ((void*)(buf), len);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::odevice::put (const std::string &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	size_t limit = buf.size();

	if (limit > buflen())
		limit = buflen();

	std::copy(buf.begin(), buf.begin() + limit, buffer());

	ssize_t count = write_vp ((void*)buffer(), limit);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::odevice::put (const std::deque<unsigned char> &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	size_t limit = buf.size();

	if (limit > buflen())
		limit = buflen();

	std::copy(buf.begin(), buf.begin() + limit, buffer());

	ssize_t count = write_vp ((void*)buffer(), limit);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

size_t my::odevice::put (const std::deque<char> &buf) {
	if (getfd() < 0)
		throw device::exception(this, EBADF);

	size_t limit = buf.size();

	if (limit > buflen())
		limit = buflen();

	std::copy(buf.begin(), buf.begin() + limit, buffer());

	ssize_t count = write_vp ((void*)buffer(), limit);

	if (count < 0)
		throw device::exception(this, errno);
	return count;
}

/* EOF */
