From a6922147d7cfb8b451852b303fd0414f459b58c4 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 1 Apr 2011 13:53:01 -0500 Subject: [PATCH] Adding a read_until option where you can insert a deliminator. --- include/serial.h | 3 +++ src/serial.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/include/serial.h b/include/serial.h index b35d256..d5b1f92 100644 --- a/include/serial.h +++ b/include/serial.h @@ -175,6 +175,9 @@ public: */ const std::string read(int size = 1); + std::string read_until(char delim, size_t size = -1); + std::string read_until(std::string delim, size_t size = -1); + /** Write length bytes from buffer to the serial port. * * @param data A char[] with data to be written to the serial port. diff --git a/src/serial.cpp b/src/serial.cpp index 6534ad8..ebe6c45 100644 --- a/src/serial.cpp +++ b/src/serial.cpp @@ -239,6 +239,64 @@ const std::string Serial::read(int size) { return return_str; } +std::string +Serial::read_until(char delim, size_t size) { + this->reading = true; + boost::asio::streambuf b(size == -1 ? size : (std::numeric_limits< std::size_t >::max)()); + boost::asio::async_read_until(*this->serial_port, b, delim, + boost::bind(&Serial::read_complete, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + if(this->timeout > timeout_zero_comparison) { // Only set a timeout_timer if there is a valid timeout + this->timeout_timer.expires_from_now(this->timeout); + this->timeout_timer.async_wait(boost::bind(&Serial::timeout_callback, this, + boost::asio::placeholders::error)); + } else if(this->nonblocking) { + this->timeout_timer.expires_from_now(boost::posix_time::milliseconds(1)); + this->timeout_timer.async_wait(boost::bind(&Serial::timeout_callback, this, + boost::asio::placeholders::error)); + } + + while(this->reading) + this->io_service.run_one(); + + b.commit(bytes_read); + + std::istream is(&b); + std::string s; + is >> s; + return s; +} + +std::string +Serial::read_until(std::string delim, size_t size) { + this->reading = true; + boost::asio::streambuf b(size == -1 ? size : (std::numeric_limits< std::size_t >::max)()); + boost::asio::async_read_until(*this->serial_port, b, delim, + boost::bind(&Serial::read_complete, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + if(this->timeout > timeout_zero_comparison) { // Only set a timeout_timer if there is a valid timeout + this->timeout_timer.expires_from_now(this->timeout); + this->timeout_timer.async_wait(boost::bind(&Serial::timeout_callback, this, + boost::asio::placeholders::error)); + } else if(this->nonblocking) { + this->timeout_timer.expires_from_now(boost::posix_time::milliseconds(1)); + this->timeout_timer.async_wait(boost::bind(&Serial::timeout_callback, this, + boost::asio::placeholders::error)); + } + + while(this->reading) + this->io_service.run_one(); + + b.commit(bytes_read); + + std::istream is(&b); + std::string s; + is >> s; + return s; +} + void Serial::read_complete(const boost::system::error_code& error, std::size_t bytes_transferred) { if(!error || error != boost::asio::error::operation_aborted) { // If there was no error OR the error wasn't operation aborted (canceled), Cancel the timer this->timeout_timer.cancel(); // will cause timeout_callback to fire with an error