Skip to content

Commit 99d9d6b

Browse files
cejkato2SiskaPavel
authored andcommitted
unirec: add unirec++ by Pavel Siska et al.
1 parent bbd1854 commit 99d9d6b

23 files changed

+2232
-5
lines changed

unirec/Makefile.am

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
ACLOCAL_AMFLAGS=-I m4
2-
DIST_SUBDIRS = tests
2+
DIST_SUBDIRS = unirec++ tests
3+
SUBDIRS = . unirec++
34

45
if ENABLE_TESTS
5-
SUBDIRS= . tests
6+
SUBDIRS += tests
67
endif
78

89
RPMDIR=RPMBUILD

unirec/configure.ac

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ AC_ARG_ENABLE([debug],
2222
[Enable build with debug symbols and without optimizations.]),
2323
[if test "$enableval" = "yes"; then
2424
CFLAGS="-std=gnu11 -Wall -g -O0 -fcommon $CFLAGS"
25-
CXXFLAGS="-std=gnu++11 -Wall -g -O0 $CXXFLAGS"
25+
CXXFLAGS="-std=c++17 -Wall -g -O0 $CXXFLAGS"
2626
fi],
2727
[CFLAGS="-std=gnu11 -Wall -g -O3 -fcommon $CFLAGS"
28-
CXXFLAGS="-std=gnu++11 -Wall -g -O3 $CXXFLAGS"])
28+
CXXFLAGS="-std=c++17 -Wall -g -O3 $CXXFLAGS"])
2929
LT_INIT()
3030
# Checks for programs.
3131
AM_PROG_CC_C_O
@@ -99,6 +99,8 @@ fi
9999

100100
AC_CONFIG_FILES([Makefile
101101
unirec.pc
102+
unirec++/unirec++.pc
103+
unirec++/Makefile
102104
unirec.spec
103105
Doxyfile
104106
tests/Makefile])

unirec/unirec++/Makefile.am

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
lib_LTLIBRARIES=libunirec++.la
2+
libunirec___la_CXXFLAGS=-fPIC
3+
libunirec___la_LDFLAGS=-ltrap -lunirec
4+
libunirec___la_SOURCES=unirec.cpp bidirectionalInterface.cpp inputInterface.cpp outputInterface.cpp
5+
6+
pkgconfigdir=$(libdir)/pkgconfig
7+
pkgconfig_DATA=unirec++.pc
8+
EXTRA_DIST=unirec++.pc.in
9+
10+
unirecincludedir=$(includedir)/unirec++
11+
unirecinclude_HEADERS=unirec++/bidirectionalInterface.hpp \
12+
unirec++/inputInterface.hpp \
13+
unirec++/ipAddress.hpp \
14+
unirec++/macAddress.hpp \
15+
unirec++/outputInterface.hpp \
16+
unirec++/trapModuleInfo.hpp \
17+
unirec++/unirecArray.hpp \
18+
unirec++/unirecException.hpp \
19+
unirec++/unirec.hpp \
20+
unirec++/unirecRecord.hpp \
21+
unirec++/unirecRecordView.hpp \
22+
unirec++/unirecTypes.hpp \
23+
unirec++/unirecTypeTraits.hpp \
24+
unirec++/urTime.hpp
25+
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/**
2+
* @file
3+
* @author Pavel Siska <[email protected]>
4+
* @brief Implementation of a bidirectional interface for sending and receiving unirec records using
5+
* the TRAP interface provided by the UniRec library.
6+
*
7+
* SPDX-License-Identifier: BSD-3-Clause
8+
*/
9+
10+
#include "unirec++/bidirectionalInterface.hpp"
11+
12+
#include <libtrap/trap.h>
13+
14+
namespace NemeaPlusPlus {
15+
16+
UnirecBidirectionalInterface::~UnirecBidirectionalInterface()
17+
{
18+
if (m_sendEoFonExit) {
19+
sendEoF();
20+
}
21+
22+
ur_free_template(m_template);
23+
}
24+
25+
UnirecBidirectionalInterface::UnirecBidirectionalInterface(
26+
uint8_t inputInterfaceID,
27+
uint8_t outputInterfaceID)
28+
: m_template(nullptr)
29+
, m_inputInterfaceID(inputInterfaceID)
30+
, m_outputInterfaceID(outputInterfaceID)
31+
, m_prioritizedDataPointer(nullptr)
32+
, m_sendEoFonExit(true)
33+
, m_EoFOnNextReceive(false)
34+
{
35+
setRequieredFormat("");
36+
}
37+
38+
std::optional<UnirecRecordView> UnirecBidirectionalInterface::receive()
39+
{
40+
const void* receivedData;
41+
uint16_t dataSize = 0;
42+
43+
if (isEoFReceived()) {
44+
throw EoFException();
45+
}
46+
47+
if (m_prioritizedDataPointer) {
48+
receivedData = m_prioritizedDataPointer;
49+
m_prioritizedDataPointer = nullptr;
50+
return UnirecRecordView(receivedData, m_template);
51+
}
52+
53+
int errorCode = trap_recv(m_inputInterfaceID, &receivedData, &dataSize);
54+
if (errorCode == TRAP_E_TIMEOUT) {
55+
return std::nullopt;
56+
}
57+
if (errorCode == TRAP_E_FORMAT_CHANGED) {
58+
m_prioritizedDataPointer = receivedData;
59+
throw FormatChangeException();
60+
}
61+
handleReceiveErrorCodes(errorCode);
62+
63+
if (dataSize <= 1) {
64+
m_EoFOnNextReceive = true;
65+
}
66+
67+
return UnirecRecordView(receivedData, m_template);
68+
}
69+
70+
bool UnirecBidirectionalInterface::isEoFReceived() const noexcept
71+
{
72+
return m_EoFOnNextReceive;
73+
}
74+
75+
void UnirecBidirectionalInterface::handleReceiveErrorCodes(int errorCode) const
76+
{
77+
if (errorCode == TRAP_E_OK) {
78+
return;
79+
}
80+
if (errorCode == TRAP_E_NOT_INITIALIZED) {
81+
throw std::runtime_error(
82+
"UnirecBidirectionalInterface::receive() has failed. Trap interface is not "
83+
"initialized.");
84+
}
85+
if (errorCode == TRAP_E_TERMINATED) {
86+
throw std::runtime_error(
87+
"UnirecBidirectionalInterface::receive() has failed. Trap interface is terminated.");
88+
}
89+
if (errorCode == TRAP_E_NOT_SELECTED) {
90+
throw std::runtime_error(
91+
"UnirecBidirectionalInterface::receive() has failed. Interface ID out of range.");
92+
}
93+
throw std::runtime_error(
94+
"UnirecBidirectionalInterface::receive() has failed. Return code: "
95+
+ std::to_string(errorCode) + ", msg: " + trap_last_error_msg);
96+
}
97+
98+
void UnirecBidirectionalInterface::setRequieredFormat(const std::string& templateSpecification)
99+
{
100+
int ret
101+
= trap_set_required_fmt(m_inputInterfaceID, TRAP_FMT_UNIREC, templateSpecification.c_str());
102+
if (ret != TRAP_E_OK) {
103+
throw std::runtime_error(
104+
"UnirecBidirectionalInterface::setRequieredFormat() has failed. Unable to set required "
105+
"format.");
106+
}
107+
}
108+
109+
void UnirecBidirectionalInterface::setReceiveTimeout(int timeout)
110+
{
111+
trap_ifcctl(TRAPIFC_INPUT, m_inputInterfaceID, TRAPCTL_SETTIMEOUT, timeout);
112+
}
113+
114+
void UnirecBidirectionalInterface::changeTemplate()
115+
{
116+
uint8_t dataType;
117+
const char* spec = nullptr;
118+
119+
int ret = trap_get_data_fmt(TRAPIFC_INPUT, m_inputInterfaceID, &dataType, &spec);
120+
if (ret != TRAP_E_OK) {
121+
throw std::runtime_error(
122+
"UnirecBidirectionalInterface::changeTemplate() has failed. Data format was not "
123+
"loaded.");
124+
}
125+
126+
m_template = ur_define_fields_and_update_template(spec, m_template);
127+
if (m_template == nullptr) {
128+
throw std::runtime_error(
129+
"UnirecBidirectionalInterface::changeTemplate() has failed. Template could not be "
130+
"edited.");
131+
}
132+
133+
std::string specCopy = spec;
134+
trap_set_data_fmt(m_outputInterfaceID, TRAP_FMT_UNIREC, specCopy.c_str());
135+
136+
ret = ur_set_input_template(m_inputInterfaceID, m_template);
137+
if (ret != TRAP_E_OK) {
138+
throw std::runtime_error("UnirecBidirectionalInterface::changeTemplate() has failed.");
139+
}
140+
141+
ret = ur_set_output_template(m_outputInterfaceID, m_template);
142+
if (ret != TRAP_E_OK) {
143+
throw std::runtime_error("UnirecBidirectionalInterface::changeTemplate() has failed.");
144+
}
145+
146+
m_unirecRecord = createUnirecRecord();
147+
}
148+
149+
UnirecRecord UnirecBidirectionalInterface::createUnirecRecord(size_t maxVariableFieldsSize)
150+
{
151+
return UnirecRecord(m_template, maxVariableFieldsSize);
152+
}
153+
154+
bool UnirecBidirectionalInterface::send(UnirecRecord& unirecRecord) const
155+
{
156+
int errorCode = trap_send(m_outputInterfaceID, unirecRecord.data(), unirecRecord.size());
157+
return handleSendErrorCodes(errorCode);
158+
}
159+
160+
bool UnirecBidirectionalInterface::send(UnirecRecordView& unirecRecordView) const
161+
{
162+
int errorCode
163+
= trap_send(m_outputInterfaceID, unirecRecordView.data(), unirecRecordView.size());
164+
return handleSendErrorCodes(errorCode);
165+
}
166+
167+
bool UnirecBidirectionalInterface::handleSendErrorCodes(int errorCode) const
168+
{
169+
if (errorCode == TRAP_E_TIMEOUT) {
170+
return false;
171+
}
172+
if (errorCode == TRAP_E_OK) {
173+
return true;
174+
}
175+
if (errorCode == TRAP_E_NOT_INITIALIZED) {
176+
throw std::runtime_error(
177+
"UnirecBidirectionalInterface::send() has failed. Trap interface is not initialized.");
178+
}
179+
if (errorCode == TRAP_E_TERMINATED) {
180+
throw std::runtime_error(
181+
"UnirecBidirectionalInterface::send() has failed. Trap interface is terminated.");
182+
}
183+
if (errorCode == TRAP_E_BAD_IFC_INDEX) {
184+
throw std::runtime_error(
185+
"UnirecBidirectionalInterface::send() has failed. Interface ID out of range.");
186+
}
187+
throw std::runtime_error(
188+
"UnirecBidirectionalInterface::send() has failed. Return code: " + std::to_string(errorCode)
189+
+ ", msg: " + trap_last_error_msg);
190+
}
191+
192+
void UnirecBidirectionalInterface::sendFlush() const
193+
{
194+
trap_send_flush(m_outputInterfaceID);
195+
}
196+
197+
void UnirecBidirectionalInterface::doNotsendEoFOnExit()
198+
{
199+
m_sendEoFonExit = false;
200+
}
201+
202+
void UnirecBidirectionalInterface::setSendTimeout(int timeout)
203+
{
204+
trap_ifcctl(TRAPIFC_OUTPUT, m_outputInterfaceID, TRAPCTL_SETTIMEOUT, timeout);
205+
}
206+
207+
void UnirecBidirectionalInterface::setSendAutoflushTimeout(int timeout)
208+
{
209+
trap_ifcctl(TRAPIFC_OUTPUT, m_outputInterfaceID, TRAPCTL_AUTOFLUSH_TIMEOUT, timeout);
210+
}
211+
212+
void UnirecBidirectionalInterface::sendEoF() const
213+
{
214+
char dummy[1] = {0};
215+
trap_send(m_outputInterfaceID, dummy, sizeof(dummy));
216+
}
217+
218+
} // namespace NemeaPlusPlus

0 commit comments

Comments
 (0)