So many changes. Broken.
[invirt/third/libt4.git] / include / rpc / file.h
1 #ifndef file_h
2 #define file_h
3
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include "include/types.h"
7 #include <sys/socket.h>
8
9 class file_t {
10     protected:
11         static const int nofile = -1;
12     private:
13         int fd_;
14
15         class flags_t {
16             private:
17                 const file_t & f_;
18                 int flags_;
19             public:
20                 flags_t(const file_t & f) : f_(f), flags_(fcntl(f_.fd_, F_GETFL, NULL)) { }
21                 ~flags_t() { fcntl(f_.fd_, F_SETFL, flags_); }
22                 operator int & () { return flags_; }
23         };
24     public:
25         inline file_t(int fd=nofile) : fd_(fd) {}
26         inline file_t(const file_t &) = delete;
27         inline file_t(file_t && other) : fd_(nofile) { std::swap(fd_, other.fd_); }
28         inline ~file_t() { close(); }
29         static inline void pipe(file_t *ends) {
30             int fds[2];
31             ends[0].close();
32             ends[1].close();
33             VERIFY(::pipe(fds) == 0);
34             ends[0].fd_ = fds[0];
35             ends[1].fd_ = fds[1];
36         }
37         inline operator int() const { if (fd_ == nofile) throw "no fd"; return fd_; }
38         inline flags_t flags() const { return {*this}; }
39         inline void close() {
40             if (fd_ != nofile)
41                 ::close(fd_);
42             fd_ = nofile;
43         }
44         template <class T> inline typename std::enable_if<std::is_pod<T>::value, ssize_t>::type
45         read(T & t) const { return ::read(fd_, &t, sizeof(T)); }
46         inline ssize_t read(void * t, size_t n) const { return ::read(fd_, t, n); }
47         template <class T> inline typename std::enable_if<std::is_pod<T>::value, ssize_t>::type
48         write(const T & t) const { return ::write(fd_, &t, sizeof(T)); }
49         inline ssize_t write(const void * t, size_t n) const { return ::write(fd_, t, n); }
50 };
51
52 class socket_t : public file_t {
53     public:
54         socket_t(int fd=nofile) : file_t(fd) {}
55         template <class T>
56         int setsockopt(int level, int option, T && value) {
57             return ::setsockopt(*this, level, option, &value, sizeof(T));
58         }
59         inline int shutdown(int how) { return ::shutdown(*this, how); }
60 };
61
62 #endif