Skip to content

Commit b8f85e5

Browse files
matthiasrichtersawenzel
authored andcommitted
Adding generic parser for o2 data format
Generic parser for an input list of messages attempting to interpret the O2 header payload sequence. The following callbacks are mandadory to be provided, e.g. through lambdas - insert function with signature (const DataHeader&, ptr, size) auto insertFct = [&] (const auto & dataheader, auto ptr, auto size) { // do something with dataheader and buffer }; - getter for the message pointer, e.g. provided std::pair is used auto getPointerFct = [] (auto & arg) {return arg.first;}; - getter for the message size, e.g. provided std::pair is used auto getSizeFct = [] (auto & arg) {return arg.second;}; Optionally, also callbacks for individual headers in the header stack can be provided.
1 parent 84e48a7 commit b8f85e5

3 files changed

Lines changed: 177 additions & 0 deletions

File tree

Algorithm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ EndForEach (_file RANGE 0 ${_length})
3838
endif()
3939

4040
set(TEST_SRCS
41+
test/o2formatparser.cxx
4142
test/headerstack.cxx
4243
test/parser.cxx
4344
test/tableview.cxx
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
#ifndef ALGORITHM_O2FORMATPARSER_H
12+
#define ALGORITHM_O2FORMATPARSER_H
13+
14+
/// @file O2FormatParser.h
15+
/// @author Matthias Richter
16+
/// @since 2017-10-18
17+
/// @brief Parser for the O2 data format
18+
19+
#include "HeaderStack.h"
20+
21+
namespace o2 {
22+
23+
namespace algorithm {
24+
25+
/**
26+
* parse an input list and try to interpret in O2 data format
27+
* O2 format consist of header-payload message pairs. The header message
28+
* always starts with the DataHeader, optionally there can be more
29+
* headers in the header stack.
30+
*
31+
* The following callbacks are mandadory to be provided, e.g. through lambdas
32+
* - insert function with signature (const DataHeader&, ptr, size)
33+
* auto insertFct = [&] (const auto & dataheader,
34+
* auto ptr,
35+
* auto size) {
36+
* // do something with dataheader and buffer
37+
* };
38+
* - getter for the message pointer, e.g. provided std::pair is used
39+
* auto getPointerFct = [] (const auto & arg) {return arg.first;};
40+
* - getter for the message size, e.g. provided std::pair is used
41+
* auto getSizeFct = [] (const auto & arg) {return arg.second;};
42+
*
43+
* Optionally, also the header stack can be parsed by specifying further
44+
* arguments. For every header supposed to be parsed, a pair of a dummy object
45+
* and callback has to be specified, e.g.
46+
* // handler callback for MyHeaderStruct
47+
* auto onMyHeaderStruct = [&] (const auto & mystruct) {
48+
* // do something with mystruct
49+
* }; // end handler callback
50+
*
51+
* parseO2Format(list, insertFct, MyHeaderStruct(), onMyHeaderStruct);
52+
*
53+
*/
54+
template<
55+
typename InputListT
56+
, typename GetPointerFctT
57+
, typename GetSizeFctT
58+
, typename InsertFctT // (const auto&, ptr, size)
59+
, typename... HeaderStackTypes // pairs of HeaderType and CallbackType
60+
>
61+
int parseO2Format(const InputListT& list,
62+
GetPointerFctT getPointer,
63+
GetSizeFctT getSize,
64+
InsertFctT insert,
65+
HeaderStackTypes&&... stackArgs
66+
)
67+
{
68+
const o2::Header::DataHeader* dh = nullptr;
69+
for (auto & part : list) {
70+
if (!dh) {
71+
// new header - payload pair, read DataHeader
72+
dh = o2::Header::get<o2::Header::DataHeader>(getPointer(part), getSize(part));
73+
if (!dh) {
74+
return -ENOMSG;
75+
}
76+
o2::algorithm::dispatchHeaderStackCallback(getPointer(part),
77+
getSize(part),
78+
stackArgs...
79+
);
80+
} else {
81+
insert(*dh, getPointer(part), getSize(part));
82+
dh = nullptr;
83+
}
84+
}
85+
if (dh) {
86+
return -ENOMSG;
87+
}
88+
return list.size()/2;
89+
}
90+
91+
} // namespace algorithm
92+
93+
} // namespace o2
94+
95+
#endif // ALGORITHM_O2FORMATPARSER_H

Algorithm/test/o2formatparser.cxx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
/// @file o2formatparser.cxx
12+
/// @author Matthias Richter
13+
/// @since 2017-10-18
14+
/// @brief Unit test for O2 format parser
15+
16+
#define BOOST_TEST_MODULE Test Algorithm HeaderStack
17+
#define BOOST_TEST_MAIN
18+
#define BOOST_TEST_DYN_LINK
19+
#include <boost/test/unit_test.hpp>
20+
#include <iostream>
21+
#include <iomanip>
22+
#include <cstring> // memcmp
23+
#include "Headers/DataHeader.h" // hexdump, DataHeader
24+
#include "../include/Algorithm/O2FormatParser.h"
25+
26+
template<typename... Targs>
27+
void hexDump(Targs... Fargs) {
28+
// a simple redirect to enable/disable the hexdump printout
29+
o2::Header::hexDump(Fargs...);
30+
}
31+
32+
BOOST_AUTO_TEST_CASE(test_o2formatparser)
33+
{
34+
std::vector<const char*> thedata = {
35+
"I'm raw data",
36+
"reconstructed data"
37+
};
38+
unsigned dataidx = 0;
39+
std::vector<o2::Header::DataHeader> dataheaders;
40+
dataheaders.emplace_back(o2::Header::DataDescription("RAWDATA"),
41+
o2::Header::DataOrigin("DET"),
42+
0,
43+
strlen(thedata[dataidx++]));
44+
dataheaders.emplace_back(o2::Header::DataDescription("RECODATA"),
45+
o2::Header::DataOrigin("DET"),
46+
0,
47+
strlen(thedata[dataidx++]));
48+
49+
std::vector<std::pair<const char*, size_t>> messages;
50+
for (dataidx = 0; dataidx < thedata.size(); ++dataidx) {
51+
messages.emplace_back(reinterpret_cast<char*>(&dataheaders[dataidx]),
52+
sizeof(o2::Header::DataHeader));
53+
messages.emplace_back(thedata[dataidx],
54+
dataheaders[dataidx].payloadSize);
55+
}
56+
57+
// handler callback for parseO2Format method
58+
auto insertFct = [&] (const auto & dataheader,
59+
auto ptr,
60+
auto size) {
61+
hexDump("header", &dataheader, sizeof(dataheader));
62+
hexDump("data", ptr, size);
63+
BOOST_CHECK(dataheader == dataheaders[dataidx]);
64+
BOOST_CHECK(strncmp(ptr, thedata[dataidx], size) == 0);
65+
++dataidx;
66+
}; // end handler callback
67+
68+
// handler callback to get the pointer for message
69+
auto getPointerFct = [] (auto arg) {return arg.first;};
70+
// handler callback to get the size for message
71+
auto getSizeFct = [] (auto arg) {return arg.second;};
72+
73+
dataidx = 0;
74+
auto result = o2::algorithm::parseO2Format(messages,
75+
getPointerFct,
76+
getSizeFct,
77+
insertFct);
78+
79+
BOOST_REQUIRE(result >= 0);
80+
BOOST_CHECK(result == 2);
81+
}

0 commit comments

Comments
 (0)