#include <sigc++/sigc++.h>
#include "mode.h"
#include "poll.h"
-#include "types.h"
namespace Msp {
namespace IO {
+struct Handle;
+
/**
Common interface for all I/O objects.
Mode get_mode() const { return mode; }
protected:
- virtual unsigned do_write(const char *, unsigned) =0;
- virtual unsigned do_read(char *, unsigned) =0;
+ virtual unsigned do_write(const char *, unsigned) = 0;
+ virtual unsigned do_read(char *, unsigned) = 0;
public:
/** Writes data from a buffer. Subject to blocking. Returns the number of
/** Returns a handle for polling. Should throw if the object does not have
an event handle. */
- virtual Handle get_event_handle() =0;
+ virtual const Handle &get_event_handle() = 0;
/** Notifies the object of an event. Used by EventDispatcher. */
void event(PollEvent);
#include <cstring>
#include <stdexcept>
#include "buffered.h"
+#include "handle.h"
using namespace std;
return end-begin;
}
-Handle Buffered::get_event_handle()
+const Handle &Buffered::get_event_handle()
{
throw logic_error("Buffered doesn't support events");
}
Mode get_current_op() const { return cur_op; }
unsigned get_current_size() const;
- virtual Handle get_event_handle();
+ virtual const Handle &get_event_handle();
};
} // namespace IO
#endif
#include <msp/core/systemerror.h>
#include "console.h"
+#include "handle_private.h"
using namespace std;
#ifdef WIN32
switch(n)
{
- case 0: handle = GetStdHandle(STD_INPUT_HANDLE); break;
- case 1: handle = GetStdHandle(STD_OUTPUT_HANDLE); break;
- case 2: handle = GetStdHandle(STD_ERROR_HANDLE); break;
+ case 0: *handle = GetStdHandle(STD_INPUT_HANDLE); break;
+ case 1: *handle = GetStdHandle(STD_OUTPUT_HANDLE); break;
+ case 2: *handle = GetStdHandle(STD_ERROR_HANDLE); break;
}
#else
- handle = n;
+ *handle = n;
- if(handle==0)
- tcgetattr(handle, &orig_attr);
+ if(n==0)
+ tcgetattr(*handle, &orig_attr);
#endif
if(n==0)
{
#ifndef WIN32
if(handle==0)
- tcsetattr(handle, TCSADRAIN, &orig_attr);
+ tcsetattr(*handle, TCSADRAIN, &orig_attr);
#endif
}
// XXX Dunno how to do this in win32
(void)b;
#else
- int flags = fcntl(0, F_GETFL);
+ int flags = fcntl(*handle, F_GETFL);
flags = (flags&~O_NONBLOCK) | (b?0:O_NONBLOCK);
- fcntl(0, F_SETFL, flags);
+ fcntl(*handle, F_SETFL, flags);
#endif
}
#ifdef WIN32
DWORD m;
- GetConsoleMode(handle, &m);
- SetConsoleMode(handle, (m&~ENABLE_ECHO_INPUT) | (e?ENABLE_ECHO_INPUT:0));
+ GetConsoleMode(*handle, &m);
+ SetConsoleMode(*handle, (m&~ENABLE_ECHO_INPUT) | (e?ENABLE_ECHO_INPUT:0));
#else
termios t;
- tcgetattr(0, &t);
+ tcgetattr(*handle, &t);
t.c_lflag = (t.c_lflag&~ECHO) | (e?ECHO:0);
- tcsetattr(0, TCSADRAIN, &t);
+ tcsetattr(*handle, TCSADRAIN, &t);
#endif
}
#ifdef WIN32
DWORD m;
- GetConsoleMode(handle, &m);
- SetConsoleMode(handle, (m&~ENABLE_LINE_INPUT) | (l?ENABLE_LINE_INPUT:0));
+ GetConsoleMode(*handle, &m);
+ SetConsoleMode(*handle, (m&~ENABLE_LINE_INPUT) | (l?ENABLE_LINE_INPUT:0));
#else
// XXX ICANON does more than just set line buffering, may need a bit more thought
termios t;
- tcgetattr(0, &t);
+ tcgetattr(*handle, &t);
t.c_lflag = (t.c_lflag&~ICANON) | (l?ICANON:0);
- tcsetattr(0, TCSADRAIN, &t);
+ tcsetattr(*handle, TCSADRAIN, &t);
#endif
}
cols = 80;
#else
struct winsize wsz;
- ioctl(handle, TIOCGWINSZ, &wsz);
+ ioctl(*handle, TIOCGWINSZ, &wsz);
rows = wsz.ws_row;
cols = wsz.ws_col;
#endif
#ifdef WIN32
DWORD ret;
- if(!WriteFile(handle, buf, len, &ret, 0))
+ if(!WriteFile(*handle, buf, len, &ret, 0))
throw system_error("WriteFile");
#else
- int ret = ::write(handle, buf, len);
+ int ret = ::write(*handle, buf, len);
if(ret==-1)
throw system_error("write");
#endif
#ifdef WIN32
DWORD ret;
- if(!ReadFile(handle, buf, len, &ret, 0))
+ if(!ReadFile(*handle, buf, len, &ret, 0))
throw system_error("ReadFile");
#else
- int ret = ::read(handle, buf, len);
+ int ret = ::read(*handle, buf, len);
if(ret==-1)
{
if(errno==EAGAIN)
return ret;
}
-Handle Console::get_event_handle()
-{
- return 0;
-}
-
Console &Console::instance(unsigned n)
{
static Console in(0);
#define MSP_IO_CONSOLE_H_
#include "base.h"
+#include "handle.h"
namespace Msp {
namespace IO {
virtual unsigned do_read(char *, unsigned);
public:
- virtual Handle get_event_handle();
+ virtual const Handle &get_event_handle() { return handle; }
static Console &instance(unsigned);
};
#include <fcntl.h>
#include <unistd.h>
#endif
+#include <msp/strings/format.h>
#include <msp/core/systemerror.h>
-#include <msp/strings/formatter.h>
#include "file.h"
+#include "handle_private.h"
using namespace std;
}
}
- handle = CreateFile(fn.c_str(), flags, 0, 0, create_flags, FILE_ATTRIBUTE_NORMAL, 0);
- if(handle==INVALID_HANDLE_VALUE)
+ *handle = CreateFile(fn.c_str(), flags, 0, 0, create_flags, FILE_ATTRIBUTE_NORMAL, 0);
+ if(!handle)
{
int err = GetLastError();
if(err==ERROR_FILE_NOT_FOUND)
if(mode&M_NONBLOCK)
flags |= O_NONBLOCK;
- handle = ::open(fn.c_str(), flags, 0666);
- if(handle==-1)
+ *handle = ::open(fn.c_str(), flags, 0666);
+ if(!handle)
{
int err = errno;
if(err==ENOENT)
void File::close()
{
- if(handle==MSP_IO_INVALID_HANDLE)
+ if(!handle)
return;
set_events(P_NONE);
signal_flush_required.emit();
#ifdef WIN32
- CloseHandle(handle);
+ CloseHandle(*handle);
#else
- ::close(handle);
+ ::close(*handle);
#endif
- handle = MSP_IO_INVALID_HANDLE;
+ handle = Handle();
signal_closed.emit();
}
if(b)
mode = (mode|M_NONBLOCK);
#ifndef WIN32
- int flags = fcntl(handle, F_GETFD);
- fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
+ int flags = fcntl(*handle, F_GETFD);
+ fcntl(*handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
#endif
}
if(mode&M_APPEND)
seek(0, S_END);
DWORD ret;
- if(WriteFile(handle, buf, size, &ret, 0)==0)
+ if(WriteFile(*handle, buf, size, &ret, 0)==0)
throw system_error("WriteFile");
#else
- int ret = ::write(handle, buf, size);
+ int ret = ::write(*handle, buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
#ifdef WIN32
DWORD ret;
- if(ReadFile(handle, buf, size, &ret, 0)==0)
+ if(ReadFile(*handle, buf, size, &ret, 0)==0)
throw system_error("ReadFile");
#else
- int ret = ::read(handle, buf, size);
+ int ret = ::read(*handle, buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
#ifndef WIN32
signal_flush_required.emit();
- fsync(handle);
+ fsync(*handle);
#endif
}
int type = sys_seek_type(st);
#ifdef WIN32
- DWORD ret = SetFilePointer(handle, off, 0, type);
+ DWORD ret = SetFilePointer(*handle, off, 0, type);
if(ret==INVALID_SET_FILE_POINTER)
throw system_error("SetFilePointer");
#else
- off_t ret = lseek(handle, off, type);
+ off_t ret = lseek(*handle, off, type);
if(ret==(off_t)-1)
throw system_error("lseek");
#endif
check_access(M_NONE);
#ifdef WIN32
- DWORD ret = SetFilePointer(handle, 0, 0, FILE_CURRENT);
+ DWORD ret = SetFilePointer(*handle, 0, 0, FILE_CURRENT);
if(ret==INVALID_SET_FILE_POINTER)
throw system_error("SetFilePointer");
#else
- off_t ret = lseek(handle, 0, SEEK_CUR);
+ off_t ret = lseek(*handle, 0, SEEK_CUR);
if(ret==(off_t)-1)
throw system_error("lseek");
#endif
void File::check_access(Mode m) const
{
- if(handle==MSP_IO_INVALID_HANDLE || (m && !(mode&m)))
+ if(!handle || (m && !(mode&m)))
throw invalid_access(m);
}
#include <string>
#include "buffered.h"
#include "filtered.h"
+#include "handle.h"
#include "seekable.h"
namespace Msp {
virtual unsigned seek(int, SeekType);
virtual unsigned tell() const;
- virtual Handle get_event_handle() { return handle; }
+ virtual const Handle &get_event_handle() { return handle; }
private:
void check_access(Mode) const;
#include <algorithm>
#include <cstring>
+#include "handle.h"
#include "memory.h"
using namespace std;
return pos-begin;
}
-Handle Memory::get_event_handle()
+const Handle &Memory::get_event_handle()
{
throw logic_error("Memory doesn't support events");
}
virtual unsigned seek(int, SeekType);
virtual unsigned tell() const { return pos-begin; }
- virtual Handle get_event_handle();
+ virtual const Handle &get_event_handle();
private:
void check_mode(Mode) const;
#endif
#include <msp/core/systemerror.h>
#include <msp/strings/formatter.h>
+#include "handle_private.h"
#include "pipe.h"
using namespace std;
{
#ifdef WIN32
string name = format("\\\\.\\pipe\\%u.%p", GetCurrentProcessId(), this);
- handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0);
- if(handle[0]==INVALID_HANDLE_VALUE)
+ *handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0);
+ if(!handle[0])
throw system_error("CreateNamedPipe");
- handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
- if(handle[1]==INVALID_HANDLE_VALUE)
+ *handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
+ if(!handle[1])
{
unsigned err = GetLastError();
- CloseHandle(handle[0]);
+ CloseHandle(*handle[0]);
throw system_error(format("CreateFile(%s)", name), err);
}
priv = new Private;
priv->overlapped = 0;
- priv->event = CreateEvent(0, true, false, 0);
+ *priv->event = CreateEvent(0, true, false, 0);
priv->buf_size = 1024;
priv->buffer = new char[priv->buf_size];
priv->buf_avail = 0;
priv->buf_next = priv->buffer;
#else
- if(pipe(handle)==-1)
+ int pipe_fd[2];
+ if(pipe(pipe_fd)==-1)
throw system_error("pipe");
+
+ *handle[0] = pipe_fd[0];
+ *handle[1] = pipe_fd[1];
#endif
set_events(P_INPUT);
{
close();
#ifdef WIN32
- CloseHandle(priv->event);
+ CloseHandle(*priv->event);
delete priv->buffer;
#endif
delete priv;
signal_flush_required.emit();
#ifdef WIN32
- CloseHandle(handle[0]);
- CloseHandle(handle[1]);
+ CloseHandle(*handle[0]);
+ CloseHandle(*handle[1]);
#else
- ::close(handle[0]);
- ::close(handle[1]);
+ ::close(*handle[0]);
+ ::close(*handle[1]);
signal_closed.emit();
#endif
}
mode = (mode|M_NONBLOCK);
#ifndef WIN32
- int flags = fcntl(handle[0], F_GETFD);
- fcntl(handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
- flags = fcntl(handle[1], F_GETFD);
- fcntl(handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
+ int flags = fcntl(*handle[0], F_GETFD);
+ fcntl(*handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
+ flags = fcntl(*handle[1], F_GETFD);
+ fcntl(*handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
#endif
}
#ifdef WIN32
DWORD ret;
- if(!WriteFile(handle[1], buf, size, &ret, 0))
+ if(!WriteFile(*handle[1], buf, size, &ret, 0))
throw system_error("WriteFile");
#else
- int ret = ::write(handle[1], buf, size);
+ int ret = ::write(*handle[1], buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
if(priv->overlapped)
{
DWORD ret;
- if(!GetOverlappedResult(handle[0], priv->overlapped, &ret, !priv->buf_avail))
+ if(!GetOverlappedResult(*handle[0], priv->overlapped, &ret, !priv->buf_avail))
throw system_error("GetOverlappedResult");
else
{
// Initiate another overlapped read in case someone is polling us
get_event_handle();
#else
- int ret = ::read(handle[0], buf, size);
+ int ret = ::read(*handle[0], buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
return ret;
}
-Handle Pipe::get_event_handle()
+const Handle &Pipe::get_event_handle()
{
#ifdef WIN32
if(!priv->overlapped && !priv->buf_avail)
{
priv->overlapped = new OVERLAPPED;
memset(priv->overlapped, 0, sizeof(OVERLAPPED));
- priv->overlapped->hEvent = priv->event;
+ priv->overlapped->hEvent = *priv->event;
DWORD ret;
priv->buf_next = priv->buffer;
- if(!ReadFile(handle[0], priv->buffer, priv->buf_size, &ret, priv->overlapped))
+ if(!ReadFile(*handle[0], priv->buffer, priv->buf_size, &ret, priv->overlapped))
{
unsigned err = GetLastError();
if(err!=ERROR_IO_PENDING)
priv->buf_avail = ret;
delete priv->overlapped;
priv->overlapped = 0;
- SetEvent(priv->event);
+ SetEvent(*priv->event);
}
}
#define MSP_IO_PIPE_H_
#include "base.h"
+#include "handle.h"
namespace Msp {
namespace IO {
virtual unsigned do_read(char *, unsigned);
public:
- virtual Handle get_event_handle();
+ virtual const Handle &get_event_handle();
};
} // namespace IO
#include <msp/strings/format.h>
#include <msp/time/units.h>
#include "base.h"
+#include "handle.h"
+#include "handle_private.h"
#include "poll.h"
using namespace std;
if(timeout<0)
timeout = INFINITE;
- DWORD ret = WaitForSingleObject(obj.get_event_handle(), timeout);
+ DWORD ret = WaitForSingleObject(*obj.get_event_handle(), timeout);
if(ret==WAIT_OBJECT_0)
return pe;
else if(ret==WAIT_FAILED)
return P_NONE;
#else
- pollfd pfd = { obj.get_event_handle(), sys_poll_event(pe), 0 };
+ pollfd pfd = { *obj.get_event_handle(), sys_poll_event(pe), 0 };
int ret = ::poll(&pfd, 1, timeout);
if(ret==-1)
priv->handles.clear();
for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
- priv->handles.push_back(i->first->get_event_handle());
+ priv->handles.push_back(*i->first->get_event_handle());
#else
priv->pfd.clear();
for(EventMap::iterator i=objects.begin(); i!=objects.end(); ++i)
{
pollfd p;
- p.fd = i->first->get_event_handle();
+ p.fd = *i->first->get_event_handle();
p.events = sys_poll_event(i->second);
priv->pfd.push_back(p);
}
#endif
#include <msp/strings/format.h>
#include <msp/core/systemerror.h>
+#include "handle_private.h"
#include "serial.h"
using namespace std;
typedef termios DeviceState;
#endif
-void get_state(Handle handle, DeviceState &state)
+void get_state(const Handle &handle, DeviceState &state)
{
#ifdef WIN32
- GetCommState(handle, &state);
+ GetCommState(*handle, &state);
#else
- tcgetattr(handle, &state);
+ tcgetattr(*handle, &state);
#endif
}
-void set_state(Handle handle, DeviceState &state)
+void set_state(const Handle &handle, DeviceState &state)
{
#ifdef WIN32
- if(SetCommState(handle, &state)==0)
+ if(SetCommState(*handle, &state)==0)
throw system_error("SetCommState");
#else
- if(tcsetattr(handle, TCSADRAIN, &state)==-1)
+ if(tcsetattr(*handle, TCSADRAIN, &state)==-1)
throw system_error("tcsetattr");
#endif
}
#ifdef WIN32
port = "\\\\.\\"+port;
- handle = CreateFile(port.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if(handle==INVALID_HANDLE_VALUE)
+ *handle = CreateFile(port.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if(!handle)
throw system_error(format("CreateFile(%s)", port));
mode = M_READ|M_WRITE;
timeouts.ReadTotalTimeoutConstant = MAXDWORD-1;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
- SetCommTimeouts(handle, &timeouts);
+ SetCommTimeouts(*handle, &timeouts);
#else
if(port.compare(0, 5, "/dev/"))
port = "/dev/"+port;
- handle = open(port.c_str(), O_RDWR);
- if(handle==-1)
+ *handle = open(port.c_str(), O_RDWR);
+ if(!handle)
throw system_error(format("open(%s)", port));
mode = M_READ|M_WRITE;
termios t;
- tcgetattr(handle, &t);
+ tcgetattr(*handle, &t);
t.c_lflag &= ~(ECHO|ICANON);
t.c_oflag &= ~OPOST;
- tcsetattr(handle, TCSADRAIN, &t);
+ tcsetattr(*handle, TCSADRAIN, &t);
#endif
if(comma!=string::npos)
void Serial::close()
{
#ifdef WIN32
- CloseHandle(handle);
+ CloseHandle(*handle);
#else
- ::close(handle);
+ ::close(*handle);
#endif
}
mode = mode&~M_NONBLOCK;
#ifndef WIN32
- int flags = fcntl(handle, F_GETFD);
- fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
+ int flags = fcntl(*handle, F_GETFD);
+ fcntl(*handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
#endif
}
#ifdef WIN32
DWORD ret;
- if(WriteFile(handle, buf, size, &ret, 0)==0)
+ if(WriteFile(*handle, buf, size, &ret, 0)==0)
throw system_error("WriteFile");
#else
- int ret = ::write(handle, buf, size);
+ int ret = ::write(*handle, buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
#ifdef WIN32
DWORD ret;
- if(ReadFile(handle, buf, size, &ret, 0)==0)
+ if(ReadFile(*handle, buf, size, &ret, 0)==0)
throw system_error("ReadFile");
#else
- int ret = ::read(handle, buf, size);
+ int ret = ::read(*handle, buf, size);
if(ret==-1)
{
if(errno==EAGAIN)
return ret;
}
-Handle Serial::get_event_handle()
+const Handle &Serial::get_event_handle()
{
#ifdef WIN32
throw logic_error("Serial port events not supported on win32 yet");
#define MSP_IO_SERIAL_H_
#include "base.h"
+#include "handle.h"
namespace Msp {
namespace IO {
virtual unsigned do_read(char *, unsigned);
public:
- virtual Handle get_event_handle();
+ virtual const Handle &get_event_handle();
};
} // namespace IO
+++ /dev/null
-#ifndef MSP_IO_TYPES_H_
-#define MSP_IO_TYPES_H_
-
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-namespace Msp {
-namespace IO {
-
-#ifdef WIN32
-typedef HANDLE Handle;
-#define MSP_IO_INVALID_HANDLE INVALID_HANDLE_VALUE
-#else
-typedef int Handle;
-#define MSP_IO_INVALID_HANDLE -1
-#endif
-
-} // namespace IO
-} // namespace Msp
-
-#endif