RInside Version 0.2.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
binarystream.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Christian Authmann
3  */
4 
5 #include "binarystream.h"
6 
7 #include <sstream>
8 #include <cstring> // memset(), strerror()
9 #include <memory>
10 #include <stdexcept>
11 
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/un.h>
16 
17 
18 BinaryStream::BinaryStream(int read_fd, int write_fd) : is_eof(false), read_fd(read_fd), write_fd(write_fd) {
19 }
20 
22  close();
23 }
24 
26  if (read_fd == write_fd)
27  write_fd = -1;
28  if (read_fd >= 0) {
30  read_fd = -1;
31  }
32  if (write_fd >= 0) {
34  write_fd = -1;
35  }
36  is_eof = true;
37 }
38 
39 BinaryStream::BinaryStream(BinaryStream &&other) : is_eof(other.is_eof), read_fd(other.read_fd), write_fd(other.write_fd) {
40  other.is_eof = true;
41  other.read_fd = -1;
42  other.write_fd = -1;
43 }
44 
46  std::swap(is_eof, other.is_eof);
47  std::swap(read_fd, other.read_fd);
48  std::swap(write_fd, other.write_fd);
49  return *this;
50 }
51 
52 
54  int new_fd = socket(AF_UNIX, SOCK_STREAM, 0);
55  if (new_fd < 0)
56  throw stream_exception();
57 
58  struct sockaddr_un server_addr;
59  memset((void *) &server_addr, 0, sizeof(server_addr));
60 
61  server_addr.sun_family = AF_UNIX;
62  strcpy(server_addr.sun_path, server_path);
63  if (connect(new_fd, (sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
64  ::close(new_fd);
65  throw stream_exception();
66  }
67 
68  return BinaryStream(new_fd, new_fd);
69 }
70 
71 
72 void BinaryStream::write(const char *buffer, size_t len) {
73  if (write_fd < 0)
74  throw stream_exception();
75 
76  //printf("Stream: writing %lu bytes\n", len);
77  auto res = ::write(write_fd, buffer, len);
78  if (res < 0 || (size_t) res != len) {
79  // strerror(errno);
80  throw stream_exception();
81  }
82 }
83 
84 size_t BinaryStream::read(char *buffer, size_t len) {
85  if (read_fd < 0 || is_eof)
86  throw stream_exception();
87 
88  //printf("Stream: reading %lu bytes\n", len);
89 
90  size_t remaining = len;
91  size_t bytes_read = 0;
92  while (remaining > 0) {
93  auto r = ::read(read_fd, buffer, remaining);
94  if (r == 0) {
95  is_eof = true;
96  throw stream_exception();
97  }
98  if (r < 0) {
99  // strerror(errno);
100  throw stream_exception();
101  }
102  bytes_read += r;
103  buffer += r;
104  remaining -= r;
105  }
106  if (bytes_read != len)
107  throw stream_exception();
108 
109  return bytes_read;
110 }
111 
112 
113 
114 namespace serialization {
115  // Strings
116  void serializer<std::string>::serialize(BinaryStream &stream, const std::string &string) {
117  size_t len = string.size();
118  if (len > (size_t) (1<<31))
120  stream.write(len);
121  stream.write(string.data(), len);
122  }
123 
125  auto len = stream.read<size_t>();
126  if (len == 0)
127  return "";
128 
129  if (len > (size_t) (1<<31))
131 
132  std::unique_ptr<char[]> buffer( new char[len] );
133  stream.read(buffer.get(), len);
134 
135  std::string string(buffer.get(), len);
136  return string;
137  }
138 
139  // Vectors
140  template <typename T>
141  void serializer<std::vector<T>>::serialize(BinaryStream &stream, const std::vector<T> &vec) {
142  size_t size = vec.size();
143  if (size > (size_t) (1<<31))
145  stream.write(size);
146  for (size_t i=0;i<size;i++)
147  stream.write(vec[i]);
148  }
149  template <typename T>
150  std::vector<T> serializer<std::vector<T>>::deserialize(BinaryStream &stream) {
151  std::vector<T> vec;
152  auto size = stream.read<size_t>();
153  if (size > (size_t) (1<<31))
155  vec.reserve(size);
156  for (size_t i=0;i<size;i++)
157  vec.push_back(stream.read<T>());
158  return vec;
159  };
160 
161  // Note: when adding more serializers, don't forget to add their declaration in binarystream.h!
162 
163  // Make sure to instantiate the vectors we need
164  template struct serializer<std::vector<int8_t>>;
165  template struct serializer<std::vector<uint8_t>>;
166  template struct serializer<std::vector<int16_t>>;
167  template struct serializer<std::vector<uint16_t>>;
168  template struct serializer<std::vector<int32_t>>;
169  template struct serializer<std::vector<uint32_t>>;
170  template struct serializer<std::vector<int64_t>>;
171  template struct serializer<std::vector<uint64_t>>;
172  template struct serializer<std::vector<float>>;
173  template struct serializer<std::vector<double>>;
174  template struct serializer<std::vector<std::string>>;
175 }
void write(const char *buffer, size_t len)
BinaryStream(int read_fd, int write_fd)
BinaryStream & operator=(const BinaryStream &)=delete
static BinaryStream connectToUnixSocket(const char *)
size_t read(char *buffer, size_t len)