/*
 *
 *
 *    device.h
 *
 *    C++ header file for class 'device.'
 *
 *    =========================================================================
 *
 *    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
 *
 *    =========================================================================
 *
 *
 */


#ifndef __DEVICE_H
#define __DEVICE_H

	#include <deque>
	#include <my++/exception.h>

	namespace my {

		/*
		 *
		 *
		 *    class device
		 *
		 *    Abstract base class for all stream devices.
		 *
		 *
		 */

		class device {
			public:
				// an exception class
				typedef my::exception_template<my::device> exception;

				// define the various flags that can be passed to 'open'
				enum open_flags {
					read = 1,
					write = 2,
					read_write = (read | write),
					not_ctl_tty = 4,
					not_symlink = 8,
					nonblocking = 16,
					synchronous = 32
				};

			public:
				// basic open and close functions
				virtual void open (const std::string &name, int modes) = 0;
				virtual void close (void) throw() = 0;

				// accessor to get descriptor
				virtual int getfd (void) throw() = 0;

				// virtual destructor
				virtual ~device (void) throw ();

				// ctor
				device (void) throw ();

			private:
				const static size_t default_buffer_size = 1024;
				unsigned char * d_buffer;
				size_t d_buflen;

			protected:
				unsigned char *buffer (void);
				size_t buflen (void);
				bool setbuf (size_t len = default_buffer_size);

		};


		/*
		 *
		 *
		 *    class idevice
		 *    class odevice
		 *
		 *    Abstract base classes for all devices that must be readable, or
		 *    writable, respectively, but not both.  Each implements enough
		 *    basic I/O operations on buffer types to be easily extended by
		 *    streamable (iostream) classes.
		 *
		 *    All derived concrete classes must implement the read_vp and/or
		 *    write_vp functions, to provide the real I/O operation in terms
		 *    of device::getfd().
		 *
		 *
		 */

		class idevice : public device {
			public:
				~idevice (void) throw () { /* noop */ };

			public:
				virtual size_t get (unsigned char *buf, size_t len);
				virtual size_t get (char *buf, size_t len);
				virtual size_t get (void *buf, size_t len);
				virtual size_t get (std::string &buf);
				virtual size_t get (std::deque<unsigned char> &buf);
				virtual size_t get (std::deque<char> &buf);

			protected:
				virtual ssize_t read_vp (void *buf, size_t len) = 0;
		};


		class odevice : public device {
			public:
				~odevice (void) throw () { /* noop */ };

			public:
				virtual size_t put (const unsigned char *buf, size_t len);
				virtual size_t put (const char *buf, size_t len);
				virtual size_t put (const void *buf, size_t len);
				virtual size_t put (const std::string &buf);
				virtual size_t put (const std::deque<unsigned char> &buf);
				virtual size_t put (const std::deque<char> &buf);

			protected:
				virtual ssize_t write_vp (const void *buf, size_t len) = 0;
		};


		/*
		 *
		 *
		 *    class iodevice
		 *
		 *    Abstract base class for all stream devices that must read and
		 *    write.  This class currently only virtually aggregates 'idevice,'
		 *    and 'odevice.'
		 *
		 *
		 */

		class iodevice : virtual public idevice, virtual public odevice {
			public:
				~iodevice (void) throw () { /* noop */ };
		};

	}

#endif /* __DEVICE_H */
