THM1176InstrumentManager 1.1
Qt Object abstraction for Metrolab THM1176
Loading...
Searching...
No Matches
SCPIInstrumentBuffer.h
Go to the documentation of this file.
1// Copyright (c) 2020 Metrolab Technology S.A., Geneva, Switzerland (www.metrolab.com)
2// See the included file LICENSE.txt for the licensing conditions.
3
7
8#pragma once
9
10#include <iterator>
11#include <algorithm>
12
13#include "Synchronization.h"
14
15using namespace MTL::Synchronization;
16
17namespace MTL {
18 namespace Instrument {
19
20 #define MTL_INSTRUMENT_BUFFER_TYPE char
21
22 //----------------------------------------------------------------------//
44 {
45 private:
46 mutable CRecursiveMutex m_Lock;
47 std::vector<MTL_INSTRUMENT_BUFFER_TYPE> m_Vector; // Used to store the data contiguously
48 size_t m_Size; // Used to handle the real size
49 public:
52 CSCPIBuffer(size_t InitialCapacity = 2048)
53 : m_Vector(), m_Size(0)
54 {
55 CLockGuard<CRecursiveMutex> Lock(m_Lock);
56
57 reserve(InitialCapacity);
58 }
59
63 CSCPIBuffer(const MTL_INSTRUMENT_BUFFER_TYPE * pData, size_t DataLen)
64 : m_Vector(), m_Size(0)
65 {
66 CLockGuard<CRecursiveMutex> Lock(m_Lock);
67
68 assign(pData, pData + DataLen);
69 }
70 virtual ~CSCPIBuffer()
71 {}
72
74 void clear()
75 {
76 CLockGuard<CRecursiveMutex> Lock(m_Lock);
77
78 m_Size = 0;
79 }
80
83 void reserve(size_t capacity)
84 {
85 CLockGuard<CRecursiveMutex> Lock(m_Lock);
86
87 if (capacity > m_Vector.size())
88 m_Vector.resize(capacity);
89 }
90
93 void resize(size_t size)
94 {
95 CLockGuard<CRecursiveMutex> Lock(m_Lock);
96
97 if (size > m_Vector.size())
98 {
99 // Ensure the vector can contain at least the required size
100 m_Vector.resize(size);
101 }
102 m_Size = size;
103 }
104
106 size_t size() const
107 {
108 CLockGuard<CRecursiveMutex> Lock(m_Lock);
109
110 return m_Size;
111 }
112
114 size_t capacity() const
115 {
116 CLockGuard<CRecursiveMutex> Lock(m_Lock);
117
118 return m_Vector.size();
119 }
120
122 std::vector<MTL_INSTRUMENT_BUFFER_TYPE>::iterator begin()
123 {
124 CLockGuard<CRecursiveMutex> Lock(m_Lock);
125
126 return m_Vector.begin();
127 }
128
130 std::vector<MTL_INSTRUMENT_BUFFER_TYPE>::const_iterator begin() const
131 {
132 CLockGuard<CRecursiveMutex> Lock(m_Lock);
133
134 return m_Vector.begin();
135 }
136
138 std::vector<MTL_INSTRUMENT_BUFFER_TYPE>::iterator end()
139 {
140 CLockGuard<CRecursiveMutex> Lock(m_Lock);
141
142 return m_Vector.begin() + m_Size;
143 }
144
146 std::vector<MTL_INSTRUMENT_BUFFER_TYPE>::const_iterator end() const
147 {
148 CLockGuard<CRecursiveMutex> Lock(m_Lock);
149
150 return m_Vector.begin() + m_Size;
151 }
152
155 {
156 CLockGuard<CRecursiveMutex> Lock(m_Lock);
157
158 return m_Vector.data();
159 }
160
162 const MTL_INSTRUMENT_BUFFER_TYPE* data() const noexcept
163 {
164 CLockGuard<CRecursiveMutex> Lock(m_Lock);
165
166 return m_Vector.data();
167 }
168
171 {
172 CLockGuard<CRecursiveMutex> Lock(m_Lock);
173
174 return m_Vector[n];
175 }
176
179 {
180 CLockGuard<CRecursiveMutex> Lock(m_Lock);
181
182 return m_Vector[n];
183 }
184
189 {
190 CLockGuard<CRecursiveMutex> Lock(m_Lock);
191
192 if (capacity() < (size_t)(Last - First))
193 reserve(Last - First);
194 std::copy(First, Last, m_Vector.begin());
195 m_Size = Last - First;
196 }
197
201 void assign(const MTL_INSTRUMENT_BUFFER_TYPE* pData, size_t n)
202 {
203 CLockGuard<CRecursiveMutex> Lock(m_Lock);
204
205 if (capacity() < n)
206 reserve(n);
207 std::copy(pData, pData + n, m_Vector.begin());
208 m_Size = n;
209 }
210 };
211
212 //----------------------------------------------------------------------//
217 {
218 private:
219 std::vector<char>::const_iterator m_Bbegin;
220 std::vector<char>::const_iterator m_Bend;
221 std::vector<char>::const_iterator m_SplitOffset;
222 public:
224 struct sToken {
225 std::vector<char>::const_iterator begin;
226 std::vector<char>::const_iterator end;
230 sToken(std::vector<char>::const_iterator b, std::vector<char>::const_iterator e)
231 : begin(b), end(e) {}
232 };
233 typedef std::vector<sToken> tTokens;
234
235 public:
239 CSCPIBufferParser(std::vector<char>::const_iterator begin, std::vector<char>::const_iterator end)
240 : m_Bbegin(begin), m_Bend(end), m_SplitOffset(begin) {}
241
243 std::vector<char>::const_iterator begin()
244 {
245 return m_Bbegin;
246 }
247
249 std::vector<char>::const_iterator end()
250 {
251 return m_Bend;
252 }
253
258 const tTokens Tokenize(const char Separator = ';', size_t Offset = 0)
259 {
260 tTokens l_Tokens;
261
262 // Check if there is data to split
263 if (m_Bbegin == m_Bend)
264 return l_Tokens;
265
266 // Find first separator (if any).
267 std::vector<char>::const_iterator l_Start = m_Bbegin + Offset;
268 std::vector<char>::const_iterator l_Next = std::find(l_Start, m_Bend, Separator);
269 l_Tokens.push_back(sToken(l_Start, l_Next));
270
271 // Find all separators
272 while (l_Next != m_Bend)
273 {
274 l_Start = l_Next + 1;
275 l_Next = std::find(l_Start, m_Bend, Separator);
276 l_Tokens.push_back(sToken(l_Start, l_Next));
277 }
278
279 // Strip white space off front.
280 const std::string l_Whitespace(" \t\n\r");
281 for (auto l_Token : l_Tokens)
282 {
283 while (std::string::npos != l_Whitespace.find(*l_Token.begin))
284 l_Token.begin++;
285 }
286
287 return l_Tokens;
288 }
289
297 bool GetNext(std::vector<char>::const_iterator & rNextBegin, std::vector<char>::const_iterator & rNextEnd, const char Separator = ';')
298 {
299 // Strip white space off front.
300 const std::string l_Whitespace(" \t\n\r");
301 while (m_SplitOffset < m_Bend &&
302 std::string::npos != l_Whitespace.find(*m_SplitOffset))
303 m_SplitOffset++;
304
305 // Did we reach the last token?
306 if (m_SplitOffset == m_Bend)
307 {
308 rNextBegin = m_Bend;
309 rNextEnd = m_Bend;
310 return false;
311 }
312
313 // Find next
314 rNextBegin = m_SplitOffset;
315 rNextEnd = std::find(m_SplitOffset, m_Bend, Separator);
316
317 // Did we reach the last token?
318 if (rNextEnd == m_Bend)
319 m_SplitOffset = m_Bend; // Set offset to the ending interator
320 else
321 m_SplitOffset = rNextEnd + 1; // Skip separator for next call
322
323 return true;
324 }
325
330 void SetNextOffset(std::vector<char>::const_iterator Offset)
331 {
332 m_SplitOffset = Offset;
333
334 // Check bounds
335 if (m_SplitOffset < m_Bbegin)
336 m_SplitOffset = m_Bbegin;
337 if (m_SplitOffset > m_Bend)
338 m_SplitOffset = m_Bbegin;
339 }
340 };
341
342}} // namespace MTL::Instrument
#define MTL_INSTRUMENT_BUFFER_TYPE
Synchronization primitives.
CSCPIBuffer(const MTL_INSTRUMENT_BUFFER_TYPE *pData, size_t DataLen)
Constructor: initialize with data provided.
void resize(size_t size)
Resize the buffer.
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::const_iterator end() const
Return a const iterator to the end of the buffer.
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::const_iterator begin() const
Return a const iterator to the beginning of the buffer.
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::iterator end()
Return an iterator to the end of the buffer.
MTL_INSTRUMENT_BUFFER_TYPE * data() noexcept
Return a pointer to the data.
void reserve(size_t capacity)
Allocate at least a given amount of space.
void clear()
Clear by setting the buffer size to zero.
CSCPIBuffer(size_t InitialCapacity=2048)
Constructor: new empty buffer.
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::iterator begin()
Return an iterator to the beginning of the buffer.
void assign(const MTL_INSTRUMENT_BUFFER_TYPE *First, const MTL_INSTRUMENT_BUFFER_TYPE *Last)
Copy the given data into the buffer: variant with begin/end.
size_t capacity() const
Return the buffer capacity (allocated size).
size_t size() const
Return the buffer size.
void assign(const MTL_INSTRUMENT_BUFFER_TYPE *pData, size_t n)
Copy the given data into the buffer: variant with pointer/size.
const MTL_INSTRUMENT_BUFFER_TYPE * data() const noexcept
Return a const pointer to the data.
MTL_INSTRUMENT_BUFFER_TYPE & operator[](size_t n)
Return byte n of the buffer.
bool GetNext(std::vector< char >::const_iterator &rNextBegin, std::vector< char >::const_iterator &rNextEnd, const char Separator=';')
Find the next token.
const tTokens Tokenize(const char Separator=';', size_t Offset=0)
Split the buffer into tokens.
std::vector< char >::const_iterator begin()
Return the beginning of the data to be parsed.
CSCPIBufferParser(std::vector< char >::const_iterator begin, std::vector< char >::const_iterator end)
Constructor.
std::vector< sToken > tTokens
List of tokens.
std::vector< char >::const_iterator end()
Return the end of the data to be parsed.
void SetNextOffset(std::vector< char >::const_iterator Offset)
Manually set the offset to the next token.
std::recursive_mutex CRecursiveMutex
Recursive Mutex.
Location of a token within a buffer.
std::vector< char >::const_iterator end
sToken(std::vector< char >::const_iterator b, std::vector< char >::const_iterator e)
Constructor.
std::vector< char >::const_iterator begin
Beginning of the token.