| THM1176InstrumentDriver 1.2 C++ API for Metrolab THM1176

Loading...
Searching...
No Matches
SCPIParsing.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// Standard includes
11#include <cstdlib>
12#include <string>
13#include <vector>
14#include <regex>
15#include <stdexcept>
16
17// Personal includes
18
19 namespace MTL {
20 namespace SCPI {
21
22// Utilities
23#define SCPIParsing_UNUSED_VAR(x) (void)x; // Prevents from unereferenced variable when compiling in release
24
25 //----------------------------------------------------------------------//
26 // Type Definitions //
27 //----------------------------------------------------------------------//
28 typedef std::vector<unsigned char> tChannel;
29 typedef std::vector<tChannel> tChannelList;
30
31 //----------------------------------------------------------------------//
32 // Conversion Utilities //
33 //----------------------------------------------------------------------//
41 template <class iterator_type>
42 bool IsArbitraryBlock(const iterator_type first, const iterator_type last, size_t & rStartOffset, size_t & rLength);
43
48 void ToArbitraryBlock(const std::string & rStr, std::string & rArbitraryBlock, bool InfiniteFormat = false);
49
55 template <class iterator_type>
56 void FromStringChannelList(iterator_type first, iterator_type last, tChannelList & rChannelList);
57
61 void ToStringChannelList(const tChannelList & rChannelList, std::string & rStr);
62
67 void FromBinaryChannelList(const char * pBinaryChanList, size_t Len, tChannelList & rChannelList);
68
72 void ToBinaryChannelList(const tChannelList & rChannelList, std::vector<char> & rBinaryChanList);
73
78 void SplitString(const std::string & rStr, std::vector<std::string> & rStrings, char Sep);
79
80
81 //----------------------------------------------------------------------//
82 // Conversion Utilities Definitions //
83 //----------------------------------------------------------------------//
84 // Template definitions must be located in the header file to avoid
85 // linking errors.
86 template <class iterator_type>
87 bool IsArbitraryBlock(const iterator_type first, const iterator_type last, size_t & rStartOffset, size_t & rLength)
88 {
89 try
90 {
91 // Check arbitrary format
92 if (*first != '#')
93 throw false;
94
95 // "Indefinite format": #0...
96 if (*(first+1) == '0')
97 {
98 rStartOffset = 2;
99 rLength = last - first - rStartOffset;
100 }
101
102 // "Definite length format": #nmmm...
103 else
104 {
105 // Get mmm
106 size_t l_PrefixLen = std::stoul(std::string(&*(first+1), 1));
107 rStartOffset = 2 + l_PrefixLen;
108 rLength = std::stoul(std::string(&*(first+2), l_PrefixLen));
109
110 // Check mmm
111 size_t l_BufferLength = last - first - rStartOffset;
112 if (rLength > l_BufferLength)
113 throw false; // String contains less data that indicated by the prefix
114 }
115 }
116 catch (bool & rE)
117 {
118 SCPIParsing_UNUSED_VAR(rE)
119 rStartOffset = 0;
120 rLength = 0;
121 return false;
122 }
123 // Possible exception thrown by stoul()
124 catch (std::invalid_argument & rE)
125 {
126 SCPIParsing_UNUSED_VAR(rE)
127 rStartOffset = 0;
128 rLength = 0;
129 return false;
130 }
131 // Possible exception thrown by stoul()
132 catch (std::out_of_range & rE)
133 {
134 SCPIParsing_UNUSED_VAR(rE)
135 rStartOffset = 0;
136 rLength = 0;
137 return false;
138 }
139
140 return true;
141 }
142 inline void ToArbitraryBlock(const std::string & rStr, std::string & rArbitraryBlock, bool InfiniteFormat)
143 {
144 if (InfiniteFormat)
145 // Infinite format: #0...
146 rArbitraryBlock = "#0" + rStr;
147 else
148 {
149 // Definite length format: #nmmm...
150 std::string l_mmm = std::to_string(rStr.length());
151 rArbitraryBlock = "#" + std::to_string(l_mmm.length()) + l_mmm + rStr;
152 }
153 }
154 template <class iterator_type>
155 void FromStringChannelList(iterator_type first, iterator_type last, tChannelList & rChannelList)
156 {
157 rChannelList.clear();
158 // Check channel list format
159 if (std::regex_match(first, last, std::regex("^\\(@[0-9!,:]*\\)[^]*$")))
160 {
161 // Check empty channel
162 if (std::regex_match(first, last, std::regex("^\\(@\\)[^]*$")))
163 return;
164
165 tChannel l_Chan;
166 for (size_t l_Index = 2, PortStart = 2; l_Index < (size_t)(last - first); l_Index++)
167 {
168 char c = *(first + l_Index);
169 if (c >= '0' && c <= '9') // In port definition
170 {
171 }
172 else if (c == '!') // End of port
173 {
174 l_Chan.push_back(atoi(std::string(first + PortStart, first + l_Index).c_str()));
175 PortStart = l_Index + 1;
176 }
177 else if (c == ',') // End of channel
178 {
179 // Close port
180 l_Chan.push_back(atoi(std::string(first + PortStart, first + l_Index).c_str()));
181 // Add channel
182 rChannelList.push_back(l_Chan);
183 l_Chan.clear();
184 PortStart = l_Index + 1;
185 }
186 else if (c == ')') // End of channel list
187 {
188 // Close port
189 l_Chan.push_back(atoi(std::string(first + PortStart, first + l_Index).c_str()));
190 // Add channel
191 rChannelList.push_back(l_Chan);
192 // Exit
193 l_Index = last - first;
194 }
195 else
196 {
197 }
198 }
199 }
200 }
201 inline void ToStringChannelList(const tChannelList & rChannelList, std::string & rStr)
202 {
203 // Open channel list string
204 rStr = "(@";
205 // Loop over channels
206 for (tChannelList::const_iterator l_it = rChannelList.begin(); l_it != rChannelList.end(); l_it++)
207 {
208 // Loop over ports
209 for (tChannel::const_iterator portit = l_it->begin(); portit != l_it->end(); portit++)
210 {
211 rStr += std::to_string(*portit);
212 if (portit + 1 != l_it->end())
213 rStr += '!';
214 }
215 if (l_it + 1 != rChannelList.end())
216 rStr += ',';
217 }
218 // Close channel list string
219 rStr += ")";
220 }
221 inline void FromBinaryChannelList(const char * pBinaryChanList, size_t Len, tChannelList & rChannelList)
222 {
223 rChannelList.clear();
224 tChannel l_Chan;
225 for (size_t l_Index = 0; l_Index < Len; l_Index++)
226 {
227 if (pBinaryChanList[l_Index] != 0)
228 l_Chan.push_back(pBinaryChanList[l_Index]);
229 else
230 {
231 rChannelList.push_back(l_Chan);
232 l_Chan.clear();
233 }
234 }
235 if (!l_Chan.empty())
236 rChannelList.push_back(l_Chan);
237 }
238 inline void ToBinaryChannelList(const tChannelList & rChannelList, std::vector<char> & rBinaryChanList)
239 {
240 rBinaryChanList.clear();
241 // Loop over channels
242 for (tChannelList::const_iterator l_it = rChannelList.begin(); l_it != rChannelList.end(); l_it++)
243 {
244 // Loop over ports
245 for (tChannel::const_iterator portit = l_it->begin(); portit != l_it->end(); portit++)
246 {
247 rBinaryChanList.push_back(*portit);
248 }
249 if (l_it + 1 != rChannelList.end())
250 rBinaryChanList.push_back(0);
251 }
252 }
253 inline void SplitString(const std::string & rStr, std::vector<std::string> & rStrings, char Sep)
254 {
255 rStrings.clear();
256
257 // Check if there is data to split
258 if (rStr.empty())
259 return;
260
261 // Find first separator (if any)
262 size_t l_Start = 0;
263 size_t l_Next = rStr.find_first_of(Sep);
264 rStrings.push_back(rStr.substr(l_Start, l_Next - l_Start));
265
266 // Find all separators
267 for (l_Start = l_Next + 1;
268 l_Next != std::string::npos;
269 l_Start = l_Next + 1)
270 {
271 l_Next = rStr.find_first_of(Sep, l_Start);
272 rStrings.push_back(rStr.substr(l_Start, l_Next - l_Start));
273 }
274 }
275
276#undef SCPIParsing_UNUSED_VAR
277
278}} // namespace MTL::SCPI
SCPIParsing_UNUSED_VAR
#define SCPIParsing_UNUSED_VAR(x)
Definition SCPIParsing.h:23
MTL::SCPI
Definition SCPIParsing.h:20
MTL::SCPI::FromBinaryChannelList
void FromBinaryChannelList(const char *pBinaryChanList, size_t Len, tChannelList &rChannelList)
Decode binary channel list.
Definition SCPIParsing.h:221
MTL::SCPI::ToStringChannelList
void ToStringChannelList(const tChannelList &rChannelList, std::string &rStr)
Encode channel list string.
Definition SCPIParsing.h:201
MTL::SCPI::tChannelList
std::vector< tChannel > tChannelList
SCPI channel list
Definition SCPIParsing.h:29
MTL::SCPI::FromStringChannelList
void FromStringChannelList(iterator_type first, iterator_type last, tChannelList &rChannelList)
Decode channel list string.
Definition SCPIParsing.h:155
MTL::SCPI::tChannel
std::vector< unsigned char > tChannel
SCPI channel
Definition SCPIParsing.h:28
MTL::SCPI::ToArbitraryBlock
void ToArbitraryBlock(const std::string &rStr, std::string &rArbitraryBlock, bool InfiniteFormat=false)
Package data as an arbitrary block.
Definition SCPIParsing.h:142
MTL::SCPI::IsArbitraryBlock
bool IsArbitraryBlock(const iterator_type first, const iterator_type last, size_t &rStartOffset, size_t &rLength)
Find arbitrary-block data within a buffer.
Definition SCPIParsing.h:87
MTL::SCPI::SplitString
void SplitString(const std::string &rStr, std::vector< std::string > &rStrings, char Sep)
Split a string into substrings separated by a given character.
Definition SCPIParsing.h:253
MTL::SCPI::ToBinaryChannelList
void ToBinaryChannelList(const tChannelList &rChannelList, std::vector< char > &rBinaryChanList)
Encode binary channel list.
Definition SCPIParsing.h:238
MTL
Definition THM1176.h:73