OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_buffers.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2024 Alec Leamas *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
25#include "model/comm_buffers.h"
26
27#include <algorithm>
28
29void OutputBuffer::Put(const std::string line) {
30 std::lock_guard<std::mutex> lock(m_mutex);
31 m_buffer.push_back(line);
32}
33
34bool OutputBuffer::Get(std::string& line) {
35 std::lock_guard<std::mutex> lock(m_mutex);
36 if (m_buffer.size() == 0) {
37 return false;
38 }
39 line = m_buffer[0];
40 m_buffer.pop_front();
41 return true;
42}
43
44void LineBuffer::Put(uint8_t ch) {
45 if (m_last_ch == '\n' && ch == '\r') {
46 // Replace possible <lf><cr> with <lf>
47 m_last_ch = 0;
48 } else if (m_last_ch == '\r' && ch == '\n') {
49 // Replace possible <cr><lf> with <lf>
50 if (m_buff.size() > 0) m_buff[m_buff.size() - 1] = '\n';
51 m_last_ch = 0;
52 } else {
53 m_buff.push_back(ch);
54 m_last_ch = ch;
55 }
56 if (ch == '\n') m_line_count += 1;
57}
58
59bool LineBuffer::HasLine() const { return m_line_count > 0; }
60
61std::vector<uint8_t> LineBuffer::GetLine() {
62 using namespace std;
63 auto nl_pos = find(m_buff.begin(), m_buff.end(), '\n');
64 if (nl_pos == m_buff.end()) {
65 return vector<uint8_t>();
66 }
67 auto line = vector<uint8_t>(m_buff.begin(), nl_pos);
68 m_buff = vector<uint8_t>(nl_pos + 1, m_buff.end());
69
70 m_line_count -= 1;
71 return line;
72}
73
75 if (m_lines.empty()) return "";
76 auto sentence = m_lines.front();
77 m_lines.pop_front();
78 return sentence;
79}
80
81void N0183Buffer::Put(uint8_t ch) {
82 switch (m_state) {
83 case State::PrefixWait:
84 // Wait until start of message
85 if (ch == '$' || ch == '!') {
86 m_line.clear();
87 m_line.push_back(ch);
88 m_state = State::Data;
89 }
90 break;
91 case State::Data:
92 // Collect data into m_line until a '*' is found
93 if (std::isprint(ch)) {
94 m_line.push_back(ch);
95 if (ch == '*') m_state = State::CsDigit1;
96 } else {
97 // Malformed? Garbage input?
98 m_state = State::PrefixWait;
99 }
100 break;
101 case State::CsDigit1:
102 // Collect first checksum digit
103 if (std::isxdigit(ch)) {
104 m_line.push_back(ch);
105 m_state = State::CsDigit2;
106 } else {
107 m_state = State::PrefixWait;
108 }
109 break;
110 case State::CsDigit2:
111 // Collect last checksum digit, push m_line to m_lines if OK
112 if (std::isxdigit(ch)) {
113 m_line.push_back(ch);
114 m_lines.emplace_back(m_line.begin(), m_line.end());
115 }
116 m_state = State::PrefixWait;
117 break;
118 }
119}
void Put(uint8_t ch)
Add a single character.
std::vector< uint8_t > GetLine()
Retrieve a line from buffer, return empty line if none available.
bool HasLine() const
Return true if a line is available to be returned by GetLine().
std::string GetSentence()
Retrieve a sentence from buffer.
void Put(uint8_t ch)
Add a single character, possibly making a sentence available.
void Put(const std::string line)
Insert line in buffer.
bool Get(std::string &line)
Retrieve a line in buffer.
Line-oriented input/output buffers.