blob: 9645356920e4742078df468ac44f4678334d9bf6 [file] [log] [blame]
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This file is part of GNU uCommon C++.
//
// GNU uCommon C++ 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.
//
// GNU uCommon C++ 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 GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
/**
* Any ucommon streaming classes that are built from std::streamio facilities
* and that support ANSI C++ stream operators.
* @file ucommon/stream.h
*/
#if defined(OLD_STDCPP) || defined(NEW_STDCPP)
#ifndef _UCOMMON_STREAM_H_
#define _UCOMMON_STREAM_H_
#ifndef _UCOMMON_CONFIG_H
#include <ucommon/platform.h>
#endif
#ifndef _UCOMMON_PROTOCOLS_H_
#include <ucommon/protocols.h>
#endif
#ifndef _UCOMMON_THREAD_H_
#include <ucommon/thread.h>
#endif
#ifndef _UCOMMON_SOCKET_H_
#include <ucommon/socket.h>
#endif
#ifndef _UCOMMON_FSYS_H_
#include <ucommon/fsys.h>
#endif
#ifndef _UCOMMON_SHELL_H_
#include <ucommon/shell.h>
#endif
#include <iostream>
NAMESPACE_UCOMMON
/**
* Common stream buffer for std C++ i/o classes. This both binds the
* character protocol to iostream and offers a common base class for all
* other c++ stdlib based streaming classes.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT StreamBuffer : protected std::streambuf, public std::iostream
{
protected:
size_t bufsize;
char *gbuf, *pbuf;
StreamBuffer();
/**
* This streambuf method is used for doing unbuffered reads
* through the establish tcp socket connection when in interactive mode.
* Also this method will handle proper use of buffers if not in
* interactive mode.
*
* @return char from tcp socket connection, EOF if not connected.
*/
int uflow();
void release(void);
void allocate(size_t size);
public:
/**
* Flush the stream input and output buffers, writes pending output.
* @return 0 on success, or error code.
*/
int sync(void);
inline bool is_open(void)
{return bufsize > 0;}
inline operator bool()
{return bufsize > 0;}
inline bool operator!()
{return bufsize == 0;}
};
/**
* Streamable tcp connection between client and server. The tcp stream
* class can represent a client connection to a server or an instance of
* a service generated by a tcp listener. As a stream class, data can
* be manipulated using the << and >> operators.
*
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT tcpstream : public StreamBuffer
{
private:
__LOCAL void allocate(unsigned size);
__LOCAL void reset(void);
protected:
socket_t so;
timeout_t timeout;
virtual ssize_t _read(char *buffer, size_t size);
virtual ssize_t _write(const char *buffer, size_t size);
virtual bool _wait(void);
/**
* Release the tcp stream and destroy the underlying socket.
*/
void release(void);
/**
* This streambuf method is used to load the input buffer
* through the established tcp socket connection.
*
* @return char from get buffer, EOF if not connected.
*/
int underflow(void);
/**
* This streambuf method is used to write the output
* buffer through the established tcp connection.
* @param ch char to push through.
* @return char pushed through.
*/
int overflow(int ch);
inline socket_t getsocket(void) const
{return so;}
public:
/**
* Copy constructor...
* @param copy for object.
*/
tcpstream(const tcpstream& copy);
/**
* Create a stream from an existing tcp listener.
* @param server to accept connection from.
* @param segsize for tcp segments and buffering.
* @param timeout for socket i/o operations.
*/
tcpstream(const TCPServer *server, unsigned segsize = 536, timeout_t timeout = 0);
/**
* Create an unconnected tcp stream object that is idle until opened.
* @param family of protocol to create.
* @param timeout for socket i/o operations.
*/
tcpstream(int family = PF_INET, timeout_t timeout = 0);
/**
* A convenience constructor that creates a connected tcp stream directly
* from an address. The socket is constructed to match the type of the
* the address family in the socket address that is passed.
* @param address of service to connect to.
* @param segsize for tcp segments and buffering.
* @param timeout for socket i/o operations.
*/
tcpstream(Socket::address& address, unsigned segsize = 536, timeout_t timeout = 0);
/**
* Destroy a tcp stream.
*/
virtual ~tcpstream();
/**
* See if stream connection is active.
* @return true if stream is active.
*/
inline operator bool() const
{return so != INVALID_SOCKET && bufsize > 0;};
/**
* See if stream is disconnected.
* @return true if stream disconnected.
*/
inline bool operator!() const
{return so == INVALID_SOCKET || bufsize == 0;};
/**
* Open a stream connection to a tcp service.
* @param address of service to access.
* @param segment buffering size to use.
*/
void open(Socket::address& address, unsigned segment = 536);
/**
* Open a stream connectoion to a host and service.
* @param host to connect to.
* @param service to connect to by name or number as string.
* @param segment buffering size to use.
*/
void open(const char *host, const char *service, unsigned segment = 536);
/**
* Close an active stream connection. This does not release the
* socket but is a disconnect.
*/
void close(void);
};
/**
* Streamable tcp connection between client and server. The tcp stream
* class can represent a client connection to a server or an instance of
* a service generated by a tcp listener. As a stream class, data can
* be manipulated using the << and >> operators.
*
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT pipestream : public StreamBuffer
{
public:
typedef enum {
RDONLY,
WRONLY,
RDWR
} access_t;
private:
__LOCAL void allocate(size_t size, access_t mode);
protected:
fsys_t rd, wr;
shell::pid_t pid;
/**
* Release the stream, detach/do not wait for the process.
*/
void release(void);
/**
* This streambuf method is used to load the input buffer
* through the established pipe connection.
*
* @return char from get buffer, EOF if not connected.
*/
int underflow(void);
/**
* This streambuf method is used to write the output
* buffer through the established pipe connection.
*
* @param ch char to push through.
* @return char pushed through.
*/
int overflow(int ch);
public:
/**
* Create an unopened pipe stream.
*/
pipestream();
/**
* Create child process and start pipe.
* @param path to execute.
* @param access mode of pipe stream.
* @param args to pass to command.
* @param env to create in child.
* @param size of buffer.
*/
pipestream(const char *command, access_t access, char **args, char **env = NULL, size_t size = 512);
/**
* Destroy a pipe stream.
*/
virtual ~pipestream();
/**
* See if stream connection is active.
* @return true if stream is active.
*/
inline operator bool() const
{return (bufsize > 0);};
/**
* See if stream is disconnected.
* @return true if stream disconnected.
*/
inline bool operator!() const
{return bufsize == 0;};
/**
* Open a stream connection to a pipe service.
* @param path to execute.
* @param access mode of stream.
* @param args to pass to command.
* @param env to create in child process.
* @param buffering size to use.
*/
void open(const char *path, access_t access, char **args, char **env = NULL, size_t buffering = 512);
/**
* Close an active stream connection. This waits for the child to
* terminate.
*/
int close(void);
/**
* Force terminate child and close.
*/
void terminate(void);
inline void cancel(void)
{terminate();}
};
/**
* Streamable tcp connection between client and server. The tcp stream
* class can represent a client connection to a server or an instance of
* a service generated by a tcp listener. As a stream class, data can
* be manipulated using the << and >> operators.
*
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT filestream : public StreamBuffer
{
public:
typedef enum {
RDONLY,
WRONLY,
RDWR
} access_t;
private:
__LOCAL void allocate(size_t size, fsys::access_t mode);
protected:
fsys_t fd;
fsys::access_t ac;
/**
* This streambuf method is used to load the input buffer
* through the established pipe connection.
*
* @return char from get buffer, EOF if not connected.
*/
int underflow(void);
/**
* This streambuf method is used to write the output
* buffer through the established pipe connection.
*
* @param ch char to push through.
* @return char pushed through.
*/
int overflow(int ch);
public:
/**
* Create an unopened pipe stream.
*/
filestream();
/**
* Create duplicate stream.
*/
filestream(const filestream& copy);
/**
* Create and open a file stream.
*/
filestream(const char *path, unsigned mode, fsys::access_t access, size_t bufsize = 512);
/**
* Open file stream.
*/
filestream(const char *path, fsys::access_t access, size_t bufsize = 512);
/**
* Destroy a file stream.
*/
virtual ~filestream();
/**
* See if stream connection is active.
* @return true if stream is active.
*/
inline operator bool() const
{return (bufsize > 0);};
/**
* See if stream is disconnected.
* @return true if stream disconnected.
*/
inline bool operator!() const
{return bufsize == 0;};
/**
* Open a stream connection to a tcp service.
*/
void open(const char *filename, fsys::access_t access, size_t buffering = 512);
/**
* Create a stream connection to a tcp service.
*/
void open(const char *filename, unsigned mode, fsys::access_t access, size_t buffering = 512);
/**
* Close an active stream connection.
*/
void close(void);
/**
* Seek position.
*/
void seek(fsys::offset_t offset);
/**
* Get error flag from last i/o operation.
* @return last error.
*/
inline int err(void) const
{return fd.err();};
};
/**
* At least with gcc, linking of stream operators was broken. This provides
* an auxillory class to solve the issue.
*/
class __EXPORT _stream_operators
{
private:
inline _stream_operators() {};
public:
static std::ostream& print(std::ostream& out, const PrintProtocol& format);
static std::istream& input(std::istream& inp, InputProtocol& format);
static std::ostream& print(std::ostream& out, const string_t& str);
static std::istream& input(std::istream& inp, string_t& str);
static std::ostream& print(std::ostream& out, const stringlist_t& list);
static std::istream& input(std::istream& in, stringlist_t& list);
};
inline std::ostream& operator<< (std::ostream& out, const PrintProtocol& format)
{return _stream_operators::print(out, format);}
inline std::istream& operator>> (std::istream& inp, InputProtocol& format)
{return _stream_operators::input(inp, format);}
inline std::ostream& operator<< (std::ostream& out, const string_t& str)
{return _stream_operators::print(out, str);}
inline std::istream& operator>> (std::istream& inp, string_t& str)
{return _stream_operators::input(inp, str);}
inline std::ostream& operator<< (std::ostream& out, const stringlist_t& list)
{return _stream_operators::print(out, list);}
inline std::istream& operator>> (std::istream& in, stringlist_t& list)
{return _stream_operators::input(in, list);}
END_NAMESPACE
#endif
#endif