GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Support void trailer type, i.e. frame consisting of only header and data · DelloStritto/AliceO2@49f6fcb

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • Algorithm
    • include/Algorithm
      • Parser.h
    • test
      • StaticSequenceAllocator.h
      • parser.cxx
      • tableview.cxx
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Algorithm/include/Algorithm/Parser.h‎

Copy file name to clipboardExpand all lines: Algorithm/include/Algorithm/Parser.h
+50-4Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,36 @@ class ForwardParser {
8686
static const size_t tailOffset = typesize<TrailerType>::size;
8787
static const size_t totalOffset = headOffset + tailOffset;
8888

89+
// alias for callback checking the header, return true if the object
90+
// is a valid header
8991
using CheckHeaderFct = std::function<bool(const HeaderType&)>;
90-
using CheckTrailerFct = std::function<bool(const TrailerType&)>;
92+
93+
// alias for the argument type to be used in the CheckTrailer function
94+
// have to forward to a valid type in case of void TrailerType in order
95+
// to allow passing by reference
96+
using CheckTrailerFctArgumentT = typename std::conditional<
97+
!std::is_void<TrailerType>::value, TrailerType, int>::type;
98+
99+
// alias for callback checking the trailer, takes reference to trailer
100+
// object if TrailerType is a valid type, no argument otherwise
101+
template <typename U>
102+
using CheckTrailerFct = typename std::conditional<
103+
!std::is_void<U>::value,
104+
std::function<bool(const CheckTrailerFctArgumentT&)>,
105+
std::function<bool()>>::type;
106+
107+
// alias for callback to get the complete frame size including header,
108+
// trailer and the data
91109
using GetFrameSizeFct = std::function<size_t(const HeaderType& )>;
110+
111+
// function callback to insert/handle one frame into, sequentially called
112+
// for all frames if the whole block has a valid format
92113
using InsertFct = std::function<bool(FrameInfo&)>;
93114

94115
template<typename InputType>
95116
int parse(const InputType* buffer, size_t bufferSize,
96117
CheckHeaderFct checkHeader,
97-
CheckTrailerFct checkTrailer,
118+
CheckTrailerFct<TrailerType> checkTrailer,
98119
GetFrameSizeFct getFrameSize,
99120
InsertFct insert) {
100121
static_assert(sizeof(InputType) == 1,
@@ -126,7 +147,7 @@ class ForwardParser {
126147
} else {
127148
auto trailerStart = buffer + position + frameSize - tailOffset;
128149
entry.trailer = reinterpret_cast<const TrailerType*>(trailerStart);
129-
if (!checkTrailer(*entry.trailer)) break;
150+
if (!CheckTrailer(entry, checkTrailer)) break;
130151
}
131152

132153
// store the extracted frame info and continue with remaining buffer
@@ -150,6 +171,29 @@ class ForwardParser {
150171
// TODO: decide about error policy
151172
return -1;
152173
}
174+
175+
template<typename InputType, typename U = TrailerType>
176+
typename std::enable_if<std::is_void<U>::value, int>::type
177+
parse(const InputType* buffer, size_t bufferSize,
178+
CheckHeaderFct checkHeader,
179+
GetFrameSizeFct getFrameSize,
180+
InsertFct insert) {
181+
auto checkTrailer = [] () {return true;};
182+
return parse(buffer, bufferSize, checkHeader, checkTrailer, getFrameSize, insert);
183+
}
184+
185+
private:
186+
template <typename U = TrailerType>
187+
typename std::enable_if<!std::is_void<U>::value, bool>::type
188+
CheckTrailer(const FrameInfo& entry, CheckTrailerFct<TrailerType>& checkTrailer) const {
189+
return checkTrailer(*entry.trailer);
190+
}
191+
192+
template <typename U = TrailerType>
193+
typename std::enable_if<std::is_void<U>::value, bool>::type
194+
CheckTrailer(const FrameInfo&, CheckTrailerFct<TrailerType>&) const {
195+
return true;
196+
}
153197
};
154198

155199
/**
@@ -198,9 +242,11 @@ class ReverseParser {
198242
PtrT payload = nullptr;
199243
size_t length = 0;
200244
};
201-
// the length offset due to header and trailer
245+
/// the length offset due to header
202246
static const size_t headOffset = typesize<HeaderType>::size;
247+
/// the length offset due to trailer
203248
static const size_t tailOffset = typesize<TrailerType>::size;
249+
/// total length offset due to header and trailer
204250
static const size_t totalOffset = headOffset + tailOffset;
205251

206252
using CheckHeaderFct = std::function<bool(const HeaderType&)>;
Collapse file

‎Algorithm/test/StaticSequenceAllocator.h‎

Copy file name to clipboardExpand all lines: Algorithm/test/StaticSequenceAllocator.h
+27-8Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,38 @@ namespace algorithm {
2121
* and a trailer
2222
*/
2323
template <typename HeaderT
24-
, typename TrailerT>
24+
, typename TrailerT = void>
2525
struct Composite {
2626
using HeaderType = HeaderT;
2727
using TrailerType = TrailerT;
2828
size_t compositeLength = 0;
29+
size_t trailerLength = 0;
2930
size_t dataLength = 0;
3031

31-
template<size_t N>
32-
constexpr Composite(const HeaderType& h, const char (&d)[N], const TrailerType& t)
32+
template<size_t N,
33+
typename U = TrailerType>
34+
constexpr Composite(const HeaderType h, const char (&d)[N],
35+
typename std::conditional<!std::is_void<U>::value, const TrailerType, int>::type t,
36+
typename std::enable_if<!std::is_void<U>::value>::type* = nullptr)
3337
: header(h)
3438
, data(d)
3539
, trailer(t)
3640
{
3741
dataLength = N;
38-
compositeLength = sizeof(HeaderType) + dataLength + sizeof(TrailerType);
42+
trailerLength = sizeof(TrailerType);
43+
compositeLength = sizeof(HeaderType) + dataLength + trailerLength;
44+
}
45+
46+
template<size_t N,
47+
typename U = TrailerType>
48+
constexpr Composite(const HeaderType& h, const char (&d)[N],
49+
typename std::enable_if<std::is_void<U>::value>::type* = nullptr)
50+
: header(h)
51+
, data(d)
52+
{
53+
dataLength = N;
54+
trailerLength = 0;
55+
compositeLength = sizeof(HeaderType) + dataLength + trailerLength;
3956
}
4057

4158
constexpr size_t getLength() const noexcept {
@@ -54,14 +71,16 @@ struct Composite {
5471
length += sizeof(HeaderType);
5572
memcpy(buffer + length, data, dataLength);
5673
length += dataLength;
57-
memcpy(buffer + length, &trailer, sizeof(TrailerType));
58-
length += sizeof(TrailerType);
74+
if (trailerLength > 0) {
75+
memcpy(buffer + length, &trailer, trailerLength);
76+
length += trailerLength;
77+
}
5978
return length;
6079
}
6180

62-
const HeaderType& header;
81+
const HeaderType header;
6382
const char* data = nullptr;
64-
const TrailerType& trailer;
83+
typename std::conditional<!std::is_void<TrailerType>::value, const TrailerType, int>::type trailer;
6584
};
6685

6786
/// recursively calculate the length of the sequence
Collapse file

‎Algorithm/test/parser.cxx‎

Copy file name to clipboardExpand all lines: Algorithm/test/parser.cxx
+121-1Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ BOOST_AUTO_TEST_CASE(test_forwardparser_header_and_trailer)
6868
return trailer.identifier == 0xaaffee00;
6969
};
7070
auto getFrameSize = [] (const typename ParserT::HeaderType& header) {
71+
// frame size includes total offset from header and trailer
7172
return header.payloadSize + ParserT::totalOffset;
7273
};
7374

@@ -93,7 +94,126 @@ BOOST_AUTO_TEST_CASE(test_forwardparser_header_and_trailer)
9394
BOOST_CHECK(memcmp(frames[2].payload, "dummydata", frames[2].length) == 0);
9495
}
9596

96-
// TODO: make a test of a composite with header and payload
97+
BOOST_AUTO_TEST_CASE(test_forwardparser_header_and_void_trailer)
98+
{
99+
using FrameT = o2::algorithm::Composite<Header>;
100+
// note: the length of the data is set in the header word
101+
using TestFrame = o2::algorithm::StaticSequenceAllocator;
102+
TestFrame tf(FrameT(16, "lotsofsillydata"),
103+
FrameT(5, "test"),
104+
FrameT(10, "dummydata")
105+
);
106+
107+
using ParserT = o2::algorithm::ForwardParser<typename FrameT::HeaderType,
108+
typename FrameT::TrailerType>;
109+
110+
auto checkHeader = [] (const typename FrameT::HeaderType& header) {
111+
return header.identifier == 0xdeadbeef;
112+
};
113+
114+
auto getFrameSize = [] (const typename ParserT::HeaderType& header) {
115+
// frame size includes total offset from header and trailer
116+
return header.payloadSize + ParserT::totalOffset;
117+
};
118+
119+
std::vector<typename ParserT::FrameInfo> frames;
120+
auto insert = [&frames] (typename ParserT::FrameInfo& info) {
121+
frames.emplace_back(info);
122+
return true;
123+
};
124+
125+
ParserT parser;
126+
auto result = parser.parse(tf.buffer.get(), tf.size(),
127+
checkHeader,
128+
getFrameSize,
129+
insert
130+
);
131+
132+
BOOST_REQUIRE(result == 3);
133+
BOOST_REQUIRE(frames.size() == 3);
134+
135+
BOOST_CHECK(memcmp(frames[0].payload, "lotsofsillydata", frames[0].length) == 0);
136+
BOOST_CHECK(memcmp(frames[1].payload, "test", frames[1].length) == 0);
137+
BOOST_CHECK(memcmp(frames[2].payload, "dummydata", frames[2].length) == 0);
138+
}
139+
140+
BOOST_AUTO_TEST_CASE(test_forwardparser_no_frames)
141+
{
142+
using FrameT = o2::algorithm::Composite<Header>;
143+
// note: the length of the data is set in the header word
144+
using TestFrame = o2::algorithm::StaticSequenceAllocator;
145+
TestFrame tf(FrameT(16, "lotsofsillydata"),
146+
FrameT(5, "test"),
147+
FrameT(10, "dummydata")
148+
);
149+
150+
using ParserT = o2::algorithm::ForwardParser<typename FrameT::HeaderType,
151+
typename FrameT::TrailerType>;
152+
153+
auto checkHeader = [] (const typename FrameT::HeaderType& header) {
154+
// simply indicate invalid header to read no frames
155+
return false;
156+
};
157+
158+
auto getFrameSize = [] (const typename ParserT::HeaderType& header) {
159+
// frame size includes total offset from header and trailer
160+
return header.payloadSize + ParserT::totalOffset;
161+
};
162+
163+
std::vector<typename ParserT::FrameInfo> frames;
164+
auto insert = [&frames] (typename ParserT::FrameInfo& info) {
165+
frames.emplace_back(info);
166+
return true;
167+
};
168+
169+
ParserT parser;
170+
auto result = parser.parse(tf.buffer.get(), tf.size(),
171+
checkHeader,
172+
getFrameSize,
173+
insert
174+
);
175+
176+
// check that there are really no frames found
177+
BOOST_REQUIRE(result == 0);
178+
}
179+
180+
BOOST_AUTO_TEST_CASE(test_forwardparser_format_error)
181+
{
182+
using FrameT = o2::algorithm::Composite<Header>;
183+
// note: the length of the data is set in the header word
184+
using TestFrame = o2::algorithm::StaticSequenceAllocator;
185+
TestFrame tf(FrameT(16, "lotsofsillydata"),
186+
FrameT(4, "test"), // <- note wrong size
187+
FrameT(10, "dummydata")
188+
);
189+
190+
using ParserT = o2::algorithm::ForwardParser<typename FrameT::HeaderType,
191+
typename FrameT::TrailerType>;
192+
193+
auto checkHeader = [] (const typename FrameT::HeaderType& header) {
194+
return header.identifier == 0xdeadbeef;
195+
};
196+
197+
auto getFrameSize = [] (const typename ParserT::HeaderType& header) {
198+
// frame size includes total offset from header and trailer
199+
return header.payloadSize + ParserT::totalOffset;
200+
};
201+
202+
std::vector<typename ParserT::FrameInfo> frames;
203+
auto insert = [&frames] (typename ParserT::FrameInfo& info) {
204+
frames.emplace_back(info);
205+
return true;
206+
};
207+
208+
ParserT parser;
209+
auto result = parser.parse(tf.buffer.get(), tf.size(),
210+
checkHeader,
211+
getFrameSize,
212+
insert
213+
);
214+
215+
BOOST_REQUIRE(result == -1);
216+
}
97217

98218
BOOST_AUTO_TEST_CASE(test_reverseparser)
99219
{
Collapse file

‎Algorithm/test/tableview.cxx‎

Copy file name to clipboardExpand all lines: Algorithm/test/tableview.cxx
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,37 @@ BOOST_AUTO_TEST_CASE(test_tableview_reverse)
120120
BOOST_CHECK(rowidx == requiredNofRowsInColumn[colidx]);
121121
}
122122
}
123+
124+
BOOST_AUTO_TEST_CASE(test_tableview_formaterror)
125+
{
126+
using FrameT = o2::algorithm::Composite<HeartbeatHeader, HeartbeatTrailer>;
127+
using TestFrame = o2::algorithm::StaticSequenceAllocator;
128+
// note: the length of the data is set in the trailer word
129+
// specifying wrong length in the second entry, no frames should be added
130+
TestFrame tf1(FrameT({0x1100000000000000}, "heartbeatdata", {0x510000000000000e}),
131+
FrameT({0x1100000000000001}, "test", {0x5100000000000004}),
132+
FrameT({0x1100000000000003}, "dummydata", {0x510000000000000a})
133+
);
134+
135+
// the payload length is set in the trailer, so we need a reverse parser
136+
using ParserT = o2::algorithm::ReverseParser<typename FrameT::HeaderType,
137+
typename FrameT::TrailerType>;
138+
139+
// define the view type for DataHeader as row descriptor,
140+
// HeartbeatHeader as column descriptor and the reverse parser
141+
using ViewType = o2::algorithm::TableView<o2::header::DataHeader,
142+
o2::header::HeartbeatHeader,
143+
ParserT>;
144+
ViewType heartbeatview;
145+
146+
o2::Header::DataHeader dh;
147+
dh.dataDescription = o2::Header::DataDescription("FIRSTSLOT");
148+
dh.dataOrigin = o2::Header::DataOrigin("TST");
149+
dh.subSpecification = 0;
150+
dh.payloadSize = 0;
151+
152+
heartbeatview.addRow(dh, tf1.buffer.get(), tf1.size());
153+
154+
BOOST_CHECK(heartbeatview.getNRows() == 0);
155+
BOOST_CHECK(heartbeatview.getNColumns() == 0);
156+
}

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.