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, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24#include "model/comm_buffers.h"
25
26#include <algorithm>
27
28void OutputBuffer::Put(const std::string line) {
29 std::lock_guard<std::mutex> lock(m_mutex);
30 m_buffer.push_back(line);
31}
32
33bool OutputBuffer::Get(std::string& line) {
34 std::lock_guard<std::mutex> lock(m_mutex);
35 if (m_buffer.size() == 0) {
36 return false;
37 }
38 line = m_buffer[0];
39 m_buffer.pop_front();
40 return true;
41}
42
43void LineBuffer::Put(uint8_t ch) {
44 if (m_last_ch == '\n' && ch == '\r') {
45 // Replace possible <lf><cr> with <lf>
46 m_last_ch = 0;
47 } else if (m_last_ch == '\r' && ch == '\n') {
48 // Replace possible <cr><lf> with <lf>
49 if (m_buff.size() > 0) m_buff[m_buff.size() - 1] = '\n';
50 m_last_ch = 0;
51 } else {
52 m_buff.push_back(ch);
53 m_last_ch = ch;
54 }
55 if (ch == '\n') m_line_count += 1;
56}
57
58bool LineBuffer::HasLine() const { return m_line_count > 0; }
59
60std::vector<uint8_t> LineBuffer::GetLine() {
61 using namespace std;
62 auto nl_pos = find(m_buff.begin(), m_buff.end(), '\n');
63 if (nl_pos == m_buff.end()) {
64 return vector<uint8_t>();
65 }
66 auto line = vector<uint8_t>(m_buff.begin(), nl_pos);
67 m_buff = vector<uint8_t>(nl_pos + 1, m_buff.end());
68
69 m_line_count -= 1;
70 return line;
71}
72
74 if (m_lines.empty()) return "";
75 auto sentence = m_lines.front();
76 m_lines.pop_front();
77 return sentence;
78}
79
80void N0183Buffer::Put(uint8_t ch) {
81 switch (m_state) {
82 case State::PrefixWait:
83 // Wait until start of message
84 if (ch == '$' || ch == '!') {
85 m_line.clear();
86 m_line.push_back(ch);
87 m_state = State::Data;
88 }
89 break;
90 case State::Data:
91 // Collect data into m_line until a '*' is found
92 // or until CR or LF character is found if CS may be missing
93 if (std::isprint(ch)) {
94 m_line.push_back(ch);
95 if (ch == '*') m_state = State::CsDigit1;
96 } else {
97 if (ch == 0x0d || ch == 0x0a) {
98 // No checksum present
99 m_lines.emplace_back(m_line.begin(), m_line.end());
100 m_state = State::PrefixWait;
101 }
102 // Malformed? Garbage input?
103 else
104 m_state = State::PrefixWait;
105 }
106 break;
107 case State::CsDigit1:
108 // Collect first checksum digit
109 if (std::isxdigit(ch)) {
110 m_line.push_back(ch);
111 m_state = State::CsDigit2;
112 } else {
113 m_state = State::PrefixWait;
114 }
115 break;
116 case State::CsDigit2:
117 // Collect last checksum digit, push m_line to m_lines if OK
118 if (std::isxdigit(ch)) {
119 m_line.push_back(ch);
120 m_lines.emplace_back(m_line.begin(), m_line.end());
121 }
122 m_state = State::PrefixWait;
123 break;
124 }
125}
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.