THM1176InstrumentDriver  1.0
C++ API for Metrolab THM1176
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 
15 using namespace MTL::Synchronization;
16 
17 namespace 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 
170  MTL_INSTRUMENT_BUFFER_TYPE& operator[] (size_t n)
171  {
172  CLockGuard<CRecursiveMutex> Lock(m_Lock);
173 
174  return m_Vector[n];
175  }
176 
178  const MTL_INSTRUMENT_BUFFER_TYPE& operator[] (size_t n) const
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;
227  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
MTL::Instrument::CSCPIBuffer::assign
void assign(const MTL_INSTRUMENT_BUFFER_TYPE *pData, size_t n)
Copy the given data into the buffer: variant with pointer/size.
Definition: SCPIInstrumentBuffer.h:201
Synchronization.h
Synchronization primitives.
MTL::Instrument::CSCPIBuffer::reserve
void reserve(size_t capacity)
Allocate at least a given amount of space.
Definition: SCPIInstrumentBuffer.h:83
MTL::Instrument::CSCPIBuffer::end
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::iterator end()
Return an iterator to the end of the buffer.
Definition: SCPIInstrumentBuffer.h:138
MTL::Instrument::CSCPIBuffer::CSCPIBuffer
CSCPIBuffer(size_t InitialCapacity=2048)
Constructor: new empty buffer.
Definition: SCPIInstrumentBuffer.h:52
MTL::Instrument::CSCPIBuffer::data
const MTL_INSTRUMENT_BUFFER_TYPE * data() const noexcept
Return a const pointer to the data.
Definition: SCPIInstrumentBuffer.h:162
MTL::Instrument::CSCPIBuffer::CSCPIBuffer
CSCPIBuffer(const MTL_INSTRUMENT_BUFFER_TYPE *pData, size_t DataLen)
Constructor: initialize with data provided.
Definition: SCPIInstrumentBuffer.h:63
MTL::Instrument::CSCPIBufferParser::GetNext
bool GetNext(std::vector< char >::const_iterator &rNextBegin, std::vector< char >::const_iterator &rNextEnd, const char Separator=';')
Find the next token.
Definition: SCPIInstrumentBuffer.h:297
MTL::Instrument::CSCPIBuffer::size
size_t size() const
Return the buffer size.
Definition: SCPIInstrumentBuffer.h:106
MTL::Synchronization
Definition: Synchronization.h:12
MTL::Instrument::CSCPIBufferParser
SCPI buffer parser.
Definition: SCPIInstrumentBuffer.h:217
MTL::Instrument::CSCPIBuffer::~CSCPIBuffer
virtual ~CSCPIBuffer()
Destructor.
Definition: SCPIInstrumentBuffer.h:70
MTL::Instrument::CSCPIBuffer::begin
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::iterator begin()
Return an iterator to the beginning of the buffer.
Definition: SCPIInstrumentBuffer.h:122
MTL::Instrument::CSCPIBufferParser::tTokens
std::vector< sToken > tTokens
List of tokens.
Definition: SCPIInstrumentBuffer.h:233
MTL::Instrument::CSCPIBufferParser::begin
std::vector< char >::const_iterator begin()
Return the beginning of the data to be parsed.
Definition: SCPIInstrumentBuffer.h:243
MTL::Instrument::CSCPIBuffer::resize
void resize(size_t size)
Resize the buffer.
Definition: SCPIInstrumentBuffer.h:93
MTL::Instrument::CSCPIBuffer::capacity
size_t capacity() const
Return the buffer capacity (allocated size).
Definition: SCPIInstrumentBuffer.h:114
MTL::Instrument::CSCPIBufferParser::sToken::end
std::vector< char >::const_iterator end
Definition: SCPIInstrumentBuffer.h:226
MTL
Definition: THM1176.h:74
MTL::Instrument::CSCPIBufferParser::Tokenize
const tTokens Tokenize(const char Separator=';', size_t Offset=0)
Split the buffer into tokens.
Definition: SCPIInstrumentBuffer.h:258
MTL::Instrument::CSCPIBufferParser::sToken::begin
std::vector< char >::const_iterator begin
Beginning of the token.
Definition: SCPIInstrumentBuffer.h:225
MTL::Instrument::CSCPIBufferParser::CSCPIBufferParser
CSCPIBufferParser(std::vector< char >::const_iterator begin, std::vector< char >::const_iterator end)
Constructor.
Definition: SCPIInstrumentBuffer.h:239
MTL_INSTRUMENT_BUFFER_TYPE
#define MTL_INSTRUMENT_BUFFER_TYPE
Definition: SCPIInstrumentBuffer.h:20
MTL::Instrument::CSCPIBufferParser::SetNextOffset
void SetNextOffset(std::vector< char >::const_iterator Offset)
Manually set the offset to the next token.
Definition: SCPIInstrumentBuffer.h:330
MTL::Instrument::CSCPIBuffer::clear
void clear()
Clear by setting the buffer size to zero.
Definition: SCPIInstrumentBuffer.h:74
MTL::Instrument::CSCPIBuffer::data
MTL_INSTRUMENT_BUFFER_TYPE * data() noexcept
Return a pointer to the data.
Definition: SCPIInstrumentBuffer.h:154
MTL::Instrument::CSCPIBufferParser::sToken
Location of a token within a buffer.
Definition: SCPIInstrumentBuffer.h:224
MTL::Synchronization::CLockGuard
Lock.
Definition: Synchronization.h:63
MTL::Instrument::CSCPIBuffer::begin
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::const_iterator begin() const
Return a const iterator to the beginning of the buffer.
Definition: SCPIInstrumentBuffer.h:130
MTL::Instrument::CSCPIBuffer
Instrument Buffer.
Definition: SCPIInstrumentBuffer.h:44
MTL::Synchronization::CRecursiveMutex
std::recursive_mutex CRecursiveMutex
Recursive Mutex.
Definition: Synchronization.h:20
MTL::Instrument::CSCPIBuffer::end
std::vector< MTL_INSTRUMENT_BUFFER_TYPE >::const_iterator end() const
Return a const iterator to the end of the buffer.
Definition: SCPIInstrumentBuffer.h:146
MTL::Instrument::CSCPIBufferParser::end
std::vector< char >::const_iterator end()
Return the end of the data to be parsed.
Definition: SCPIInstrumentBuffer.h:249
MTL::Instrument::CSCPIBuffer::assign
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.
Definition: SCPIInstrumentBuffer.h:188