OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_buffers.h
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#ifndef COMM_BUFFERS_H_
25#define COMM_BUFFERS_H_
26
27#include <deque>
28#include <memory>
29#include <mutex>
30#include <stdexcept>
31#include <string>
32#include <vector>
33
34#ifdef _MSC_VER
35typedef unsigned __int8 uint8_t;
36#else
37#include <cstdint>
38#endif
39
40class BufferError : public std::logic_error {
41public:
42 BufferError(const std::string& why) : logic_error(why) {};
43};
44
47public:
49 void Put(const std::string line);
50
55 bool Get(std::string& line);
56
57private:
58 std::deque<std::string> m_buffer;
59 std::mutex m_mutex;
60};
61
64public:
66 void Put(uint8_t ch);
67
69 bool HasLine() const;
70
72 std::vector<uint8_t> GetLine();
73
74 LineBuffer() : m_line_count(0), m_last_ch('\n') {}
75
76private:
77 std::vector<uint8_t> m_buff;
78 int m_line_count;
79 uint8_t m_last_ch;
80};
81
84public:
86 void Put(uint8_t ch);
87
89 bool HasSentence() const { return !m_lines.empty(); }
90
95 std::string GetSentence();
96
97 N0183Buffer() : m_state(State::PrefixWait) {}
98
99private:
100 std::deque<std::string> m_lines;
101 std::vector<uint8_t> m_line;
102 enum class State { PrefixWait, Data, CsDigit1, CsDigit2 } m_state;
103};
104
106template <class T>
108public:
109 explicit CircularBuffer(size_t size)
110 : m_buf(std::unique_ptr<T[]>(new T[size])),
111 m_max_size(size),
112 m_head(0),
113 m_tail(0),
114 m_full(false) {}
115
117 void Reset() noexcept {
118 std::lock_guard<std::mutex> lock(m_mutex);
119 m_head = 0;
120 m_tail = 0;
121 m_full = false;
122 }
123
125 size_t Capacity() const noexcept { return m_max_size; }
126
128 size_t Size() const noexcept {
129 std::lock_guard<std::mutex> lock(m_mutex);
130 size_t size = m_max_size;
131 if (!m_full)
132 size = m_head >= m_tail ? m_head - m_tail : m_head + m_max_size - m_tail;
133 return size;
134 }
135
137 bool IsEmpty() const noexcept {
138 std::lock_guard<std::mutex> lock(m_mutex);
139 return (!m_full && (m_head == m_tail));
140 }
141
143 bool IsFull() const noexcept {
144 std::lock_guard<std::mutex> lock(m_mutex);
145 return m_full;
146 }
147
152 bool SafePut(const T& item) noexcept {
153 std::lock_guard<std::mutex> lock(m_mutex);
154 if (m_full) return false;
155 DoPut(item);
156 return true;
157 }
158
160 void Put(const T& item) {
161 std::lock_guard<std::mutex> lock(m_mutex);
162 if (m_full) throw BufferError("Put(): full buffer");
163 DoPut(item);
164 }
165
167 T Get() {
168 std::lock_guard<std::mutex> lock(m_mutex);
169 if (!m_full && m_head == m_tail) throw BufferError("Get(): empty buffer");
170 return DoGet();
171 }
172
177 bool Get(T& item) noexcept {
178 std::lock_guard<std::mutex> lock(m_mutex);
179 if (!m_full && m_head == m_tail) return false;
180 item = DoGet();
181 return true;
182 }
183
184 const T& Peek() const {
185 std::lock_guard<std::mutex> lock(m_mutex);
186 if (!m_full && m_head == m_tail) throw BufferError("Peek(): empty buffer");
187 return m_buf[m_tail];
188 }
189
190 bool Peek(T& item) const noexcept {
191 std::lock_guard<std::mutex> lock(m_mutex);
192 if (!m_full && m_head == m_tail) return false;
193 item = m_buf[m_tail];
194 return true;
195 }
196
197private:
198 mutable std::mutex m_mutex;
199 std::unique_ptr<T[]> m_buf;
200 const size_t m_max_size;
201 size_t m_head;
202 size_t m_tail;
203 bool m_full;
204
205 void DoPut(const T& item) {
206 m_buf[m_head] = item;
207 if (m_full) m_tail = (m_tail + 1) % m_max_size;
208 m_head = (m_head + 1) % m_max_size;
209 m_full = m_head == m_tail;
210 }
211
212 // Read data and advance the tail (we now have a free space)
213 T DoGet() {
214 auto val = m_buf[m_tail];
215 m_full = false;
216 m_tail = (m_tail + 1) % m_max_size;
217 return val;
218 }
219};
220
221#endif // COMM_BUFFERS_H_
Fixed size, synchronized FIFO buffer.
bool IsEmpty() const noexcept
Return true if buffer is empty.
void Reset() noexcept
Reset internal state, ditch possible contained data.
size_t Capacity() const noexcept
Return buffer max size.
size_t Size() const noexcept
Return actual size.
bool Get(T &item) noexcept
Retrieve item from buffer without throwing exceptions.
T Get()
Get item from buff; throw BufferError if empty.
bool SafePut(const T &item) noexcept
Add item to buffer without throwing exceptions.
void Put(const T &item)
Add item to buffer; throw BufferError if full.
bool IsFull() const noexcept
Return true if buffer is full.
Assembles input characters to lines.
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().
Assemble characters to NMEA0183 sentences.
bool HasSentence() const
Return true if a sentence is available to be returned by GetSentence()
std::string GetSentence()
Retrieve a sentence from buffer.
void Put(uint8_t ch)
Add a single character, possibly making a sentence available.
Synchronized buffer for outbound, line oriented data.
void Put(const std::string line)
Insert line in buffer.
bool Get(std::string &line)
Retrieve a line in buffer.