]> Git Repo - serial.git/blob - src/serial.cc
Changes after testing on Windows. Everything seems to work, but it could use some...
[serial.git] / src / serial.cc
1 /* Copyright 2012 William Woodall and John Harrison */
2 //#include <alloca.h>
3
4 #include "serial/serial.h"
5
6 #ifdef _WIN32
7 #include "serial/impl/win.h"
8 #else
9 #include "serial/impl/unix.h"
10 #endif
11
12 using std::invalid_argument;
13 using std::min;
14 using std::numeric_limits;
15 using std::vector;
16 using std::size_t;
17 using std::string;
18
19 using serial::Serial;
20 using serial::SerialExecption;
21 using serial::IOException;
22 using serial::bytesize_t;
23 using serial::parity_t;
24 using serial::stopbits_t;
25 using serial::flowcontrol_t;
26
27 class Serial::ScopedReadLock {
28 public:
29   ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) {
30     this->pimpl_->readLock();
31   }
32   ~ScopedReadLock() {
33     this->pimpl_->readUnlock();
34   }
35 private:
36   // Disable copy constructors
37   ScopedReadLock(const ScopedReadLock&);
38   void operator=(const ScopedReadLock&);
39   const ScopedReadLock& operator=(ScopedReadLock);
40
41   SerialImpl *pimpl_;
42 };
43
44 class Serial::ScopedWriteLock {
45 public:
46   ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) {
47     this->pimpl_->writeLock();
48   }
49   ~ScopedWriteLock() {
50     this->pimpl_->writeUnlock();
51   }
52 private:
53   // Disable copy constructors
54   ScopedWriteLock(const ScopedWriteLock&);
55   void operator=(const ScopedWriteLock&);
56   const ScopedWriteLock& operator=(ScopedWriteLock);
57   SerialImpl *pimpl_;
58 };
59
60 Serial::Serial (const string &port, uint32_t baudrate, serial::Timeout timeout,
61                 bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
62                 flowcontrol_t flowcontrol)
63  : read_cache_(""), pimpl_(new SerialImpl (port, baudrate, bytesize, parity,
64                                            stopbits, flowcontrol))
65 {
66   pimpl_->setTimeout(timeout);
67 }
68
69 Serial::~Serial ()
70 {
71   delete pimpl_;
72 }
73
74 void
75 Serial::open ()
76 {
77   pimpl_->open ();
78 }
79
80 void
81 Serial::close ()
82 {
83   pimpl_->close ();
84 }
85
86 bool
87 Serial::isOpen () const
88 {
89   return pimpl_->isOpen ();
90 }
91
92 size_t
93 Serial::available ()
94 {
95   return pimpl_->available ();
96 }
97
98 size_t
99 Serial::read_ (uint8_t *buffer, size_t size)
100 {
101   return this->pimpl_->read (buffer, size);
102 }
103
104 size_t
105 Serial::read (uint8_t *buffer, size_t size)
106 {
107   ScopedReadLock (this->pimpl_);
108   return this->pimpl_->read (buffer, size);
109 }
110
111 size_t
112 Serial::read (std::vector<uint8_t> &buffer, size_t size)
113 {
114   ScopedReadLock (this->pimpl_);
115   uint8_t *buffer_ = new uint8_t[size];
116   size_t bytes_read = this->pimpl_->read (buffer_, size);
117   buffer.insert (buffer.end (), buffer_, buffer_+bytes_read);
118   delete[] buffer_;
119   return bytes_read;
120 }
121
122 size_t
123 Serial::read (std::string &buffer, size_t size)
124 {
125   ScopedReadLock (this->pimpl_);
126   uint8_t *buffer_ = new uint8_t[size];
127   size_t bytes_read = this->pimpl_->read (buffer_, size);
128   buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read);
129   delete[] buffer_;
130   return bytes_read;
131 }
132
133 string
134 Serial::read (size_t size)
135 {
136   std::string buffer;
137   this->read (buffer, size);
138   return buffer;
139 }
140
141 size_t
142 Serial::readline (string &buffer, size_t size, string eol)
143 {
144   ScopedReadLock (this->pimpl_);
145   size_t eol_len = eol.length ();
146   uint8_t *buffer_ = static_cast<uint8_t*>
147                               (alloca (size * sizeof (uint8_t)));
148   size_t read_so_far = 0;
149   while (true)
150   {
151     size_t bytes_read = this->read_ (buffer_ + read_so_far, 1);
152     read_so_far += bytes_read;
153     if (bytes_read == 0) {
154       break; // Timeout occured on reading 1 byte
155     }
156     if (string (reinterpret_cast<const char*>
157          (buffer_ + read_so_far - eol_len), eol_len) == eol) {
158       break; // EOL found
159     }
160     if (read_so_far == size) {
161       break; // Reached the maximum read length
162     }
163   }
164   buffer.append(reinterpret_cast<const char*> (buffer_), read_so_far);
165   return read_so_far;
166 }
167
168 string
169 Serial::readline (size_t size, string eol)
170 {
171   std::string buffer;
172   this->readline (buffer, size, eol);
173   return buffer;
174 }
175
176 vector<string>
177 Serial::readlines (size_t size, string eol)
178 {
179   ScopedReadLock (this->pimpl_);
180   std::vector<std::string> lines;
181   size_t eol_len = eol.length ();
182   uint8_t *buffer_ = static_cast<uint8_t*>
183     (alloca (size * sizeof (uint8_t)));
184   size_t read_so_far = 0;
185   size_t start_of_line = 0;
186   while (read_so_far < size) {
187     size_t bytes_read = this->read_ (buffer_+read_so_far, 1);
188     read_so_far += bytes_read;
189     if (bytes_read == 0) {
190       if (start_of_line != read_so_far) {
191         lines.push_back (
192           string (reinterpret_cast<const char*> (buffer_ + start_of_line),
193             read_so_far - start_of_line));
194       }
195       break; // Timeout occured on reading 1 byte
196     }
197     if (string (reinterpret_cast<const char*>
198          (buffer_ + read_so_far - eol_len), eol_len) == eol) {
199       // EOL found
200       lines.push_back(
201         string(reinterpret_cast<const char*> (buffer_ + start_of_line),
202           read_so_far - start_of_line));
203       start_of_line = read_so_far;
204     }
205     if (read_so_far == size) {
206       if (start_of_line != read_so_far) {
207         lines.push_back(
208           string(reinterpret_cast<const char*> (buffer_ + start_of_line),
209             read_so_far - start_of_line));
210       }
211       break; // Reached the maximum read length
212     }
213   }
214   return lines;
215 }
216
217 size_t
218 Serial::write (const string &data)
219 {
220   ScopedWriteLock(this->pimpl_);
221   return this->write_ (reinterpret_cast<const uint8_t*>(data.c_str()),
222                        data.length());
223 }
224
225 size_t
226 Serial::write (const std::vector<uint8_t> &data)
227 {
228   ScopedWriteLock(this->pimpl_);
229   return this->write_ (&data[0], data.size());
230 }
231
232 size_t
233 Serial::write (const uint8_t *data, size_t size)
234 {
235   ScopedWriteLock(this->pimpl_);
236   return this->write_(data, size);
237 }
238
239 size_t
240 Serial::write_ (const uint8_t *data, size_t length)
241 {
242   return pimpl_->write (data, length);
243 }
244
245 void
246 Serial::setPort (const string &port)
247 {
248   ScopedReadLock(this->pimpl_);
249   ScopedWriteLock(this->pimpl_);
250   bool was_open = pimpl_->isOpen ();
251   if (was_open) close();
252   pimpl_->setPort (port);
253   if (was_open) open ();
254 }
255
256 string
257 Serial::getPort () const
258 {
259   return pimpl_->getPort ();
260 }
261
262 void
263 Serial::setTimeout (serial::Timeout &timeout)
264 {
265   pimpl_->setTimeout (timeout);
266 }
267
268 serial::Timeout
269 Serial::getTimeout () const {
270   return pimpl_->getTimeout ();
271 }
272
273 void
274 Serial::setBaudrate (uint32_t baudrate)
275 {
276   pimpl_->setBaudrate (baudrate);
277 }
278
279 uint32_t
280 Serial::getBaudrate () const
281 {
282   return uint32_t(pimpl_->getBaudrate ());
283 }
284
285 void
286 Serial::setBytesize (bytesize_t bytesize)
287 {
288   pimpl_->setBytesize (bytesize);
289 }
290
291 bytesize_t
292 Serial::getBytesize () const
293 {
294   return pimpl_->getBytesize ();
295 }
296
297 void
298 Serial::setParity (parity_t parity)
299 {
300   pimpl_->setParity (parity);
301 }
302
303 parity_t
304 Serial::getParity () const
305 {
306   return pimpl_->getParity ();
307 }
308
309 void
310 Serial::setStopbits (stopbits_t stopbits)
311 {
312   pimpl_->setStopbits (stopbits);
313 }
314
315 stopbits_t
316 Serial::getStopbits () const
317 {
318   return pimpl_->getStopbits ();
319 }
320
321 void
322 Serial::setFlowcontrol (flowcontrol_t flowcontrol)
323 {
324   pimpl_->setFlowcontrol (flowcontrol);
325 }
326
327 flowcontrol_t
328 Serial::getFlowcontrol () const
329 {
330   return pimpl_->getFlowcontrol ();
331 }
332
333 void Serial::flush ()
334 {
335   ScopedReadLock(this->pimpl_);
336   ScopedWriteLock(this->pimpl_);
337   pimpl_->flush ();
338   read_cache_.clear ();
339 }
340
341 void Serial::flushInput ()
342 {
343   ScopedReadLock(this->pimpl_);
344   pimpl_->flushInput ();
345 }
346
347 void Serial::flushOutput ()
348 {
349   ScopedWriteLock(this->pimpl_);
350   pimpl_->flushOutput ();
351   read_cache_.clear ();
352 }
353
354 void Serial::sendBreak (int duration)
355 {
356   pimpl_->sendBreak (duration);
357 }
358
359 void Serial::setBreak (bool level)
360 {
361   pimpl_->setBreak (level);
362 }
363
364 void Serial::setRTS (bool level)
365 {
366   pimpl_->setRTS (level);
367 }
368
369 void Serial::setDTR (bool level)
370 {
371   pimpl_->setDTR (level);
372 }
373
374 bool Serial::waitForChange()
375 {
376   return pimpl_->waitForChange();
377 }
378
379 bool Serial::getCTS ()
380 {
381   return pimpl_->getCTS ();
382 }
383
384 bool Serial::getDSR ()
385 {
386   return pimpl_->getDSR ();
387 }
388
389 bool Serial::getRI ()
390 {
391   return pimpl_->getRI ();
392 }
393
394 bool Serial::getCD ()
395 {
396   return pimpl_->getCD ();
397 }
This page took 0.04729 seconds and 4 git commands to generate.