@@ -23,11 +23,13 @@ namespace o2 { |
23 | 23 |
|
24 | 24 | namespace algorithm { |
25 | 25 |
|
26 | | -// TODO there is probably a standard way? |
| 26 | +/// helper function returning size of type with a specialization for |
| 27 | +/// void returning 0 |
27 | 28 | template<typename T> |
28 | 29 | struct typesize { |
29 | 30 | static const size_t size = sizeof(T); |
30 | 31 | }; |
| 32 | +// specialization for void |
31 | 33 | template<> |
32 | 34 | struct typesize<void> { |
33 | 35 | static const size_t size = 0; |
@@ -38,8 +40,12 @@ struct typesize<void> { |
38 | 40 | * Parser for a sequence of frames with header, trailer and variable payload. |
39 | 41 | * The size is expected to be part of the header. |
40 | 42 | * |
| 43 | + * Trailer type can be void, which is also the default template parameter. That |
| 44 | + * allows to define a frame consisting of only header and data. |
| 45 | + * |
41 | 46 | * Usage: |
42 | | - * ForwardParser<SomeHeaderType, SomeTrailerType> SomeParser; |
| 47 | + * <pre> |
| 48 | + * using SomeParser = ForwardParser<SomeHeaderType, SomeTrailerType>; |
43 | 49 | * SomeParser parser; |
44 | 50 | * std::vector<typename SomeParser::FrameInfo> frames; |
45 | 51 | * parser.parse(ptr, size, |
@@ -62,6 +68,28 @@ struct typesize<void> { |
62 | 68 | * return true; |
63 | 69 | * } |
64 | 70 | * ) |
| 71 | + * |
| 72 | + * // a reduced version without trailer check callback |
| 73 | + * using SomeParser = ForwardParser<SomeHeaderType>; |
| 74 | + * SomeParser parser; |
| 75 | + * std::vector<typename SomeParser::FrameInfo> frames; |
| 76 | + * parser.parse(ptr, size, |
| 77 | + * [] (const typename SomeParser::HeaderType& h) { |
| 78 | + * // check the header |
| 79 | + * return true; |
| 80 | + * }, |
| 81 | + * [] (const typename SomeParser::HeaderType& h) { |
| 82 | + * // get the size of the frame including payload |
| 83 | + * // and header and trailer size, e.g. payload size |
| 84 | + * // from a header member |
| 85 | + * return h.payloadSize + SomeParser::totalOffset; |
| 86 | + * }, |
| 87 | + * [&frames] (typename SomeParser::FrameInfo& info) { |
| 88 | + * frames.emplace_back(info); |
| 89 | + * return true; |
| 90 | + * } |
| 91 | + * ) |
| 92 | + * </pre> |
65 | 93 | */ |
66 | 94 | template<typename HeaderT, |
67 | 95 | typename TrailerT = void |
@@ -72,6 +100,8 @@ class ForwardParser { |
72 | 100 | using TrailerType = TrailerT; |
73 | 101 | using PayloadType = unsigned char; |
74 | 102 |
|
| 103 | + /// @struct FrameInfo |
| 104 | + /// a compound of header, data, and trailer |
75 | 105 | struct FrameInfo { |
76 | 106 | using PtrT = const PayloadType*; |
77 | 107 |
|
@@ -81,37 +111,42 @@ class ForwardParser { |
81 | 111 | size_t length = 0; |
82 | 112 | }; |
83 | 113 |
|
84 | | - // the length offset due to header and trailer |
| 114 | + /// the length offset due to header |
85 | 115 | static const size_t headOffset = typesize<HeaderType>::size; |
| 116 | + /// the length offset due to trailer |
86 | 117 | static const size_t tailOffset = typesize<TrailerType>::size; |
| 118 | + /// total length offset due to header and trailer |
87 | 119 | static const size_t totalOffset = headOffset + tailOffset; |
88 | 120 |
|
89 | | - // alias for callback checking the header, return true if the object |
90 | | - // is a valid header |
| 121 | + /// alias for callback checking the header, return true if the object |
| 122 | + /// is a valid header |
91 | 123 | using CheckHeaderFct = std::function<bool(const HeaderType&)>; |
92 | 124 |
|
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 |
| 125 | + /// alias for the argument type to be used in the CheckTrailer function |
| 126 | + /// have to forward to a valid type in case of void TrailerType in order |
| 127 | + /// to allow passing by reference |
96 | 128 | using CheckTrailerFctArgumentT = typename std::conditional< |
97 | 129 | !std::is_void<TrailerType>::value, TrailerType, int>::type; |
98 | 130 |
|
99 | | - // alias for callback checking the trailer, takes reference to trailer |
100 | | - // object if TrailerType is a valid type, no argument otherwise |
| 131 | + /// alias for callback checking the trailer, takes reference to trailer |
| 132 | + /// object if TrailerType is a valid type, no argument otherwise |
101 | 133 | template <typename U> |
102 | 134 | using CheckTrailerFct = typename std::conditional< |
103 | 135 | !std::is_void<U>::value, |
104 | 136 | std::function<bool(const CheckTrailerFctArgumentT&)>, |
105 | 137 | std::function<bool()>>::type; |
106 | 138 |
|
107 | | - // alias for callback to get the complete frame size including header, |
108 | | - // trailer and the data |
| 139 | + /// alias for callback to get the complete frame size including header, |
| 140 | + /// trailer and the data |
109 | 141 | using GetFrameSizeFct = std::function<size_t(const HeaderType& )>; |
110 | 142 |
|
111 | | - // function callback to insert/handle one frame into, sequentially called |
112 | | - // for all frames if the whole block has a valid format |
| 143 | + /// function callback to insert/handle one frame into, sequentially called |
| 144 | + /// for all frames if the whole block has a valid format |
113 | 145 | using InsertFct = std::function<bool(FrameInfo&)>; |
114 | 146 |
|
| 147 | + /// Parse buffer of size bufferSize, requires callbacks to check header |
| 148 | + /// trailer, the frame size, and insert callback to handle a FrameInfo |
| 149 | + /// object. |
115 | 150 | template<typename InputType> |
116 | 151 | int parse(const InputType* buffer, size_t bufferSize, |
117 | 152 | CheckHeaderFct checkHeader, |
@@ -172,6 +207,10 @@ class ForwardParser { |
172 | 207 | return -1; |
173 | 208 | } |
174 | 209 |
|
| 210 | + /// Parse buffer of size bufferSize, specialization skipping the trailer |
| 211 | + /// check, e.g. when its type is void, or when the integrity of the trailer |
| 212 | + /// is not relevant. Requires callbacks to check header, frame size, and |
| 213 | + /// insert callback to handle a FrameInfo object. |
175 | 214 | template<typename InputType, typename U = TrailerType> |
176 | 215 | typename std::enable_if<std::is_void<U>::value, int>::type |
177 | 216 | parse(const InputType* buffer, size_t bufferSize, |
@@ -183,6 +222,8 @@ class ForwardParser { |
183 | 222 | } |
184 | 223 |
|
185 | 224 | private: |
| 225 | + /// internal function to check the trailer, distinguishes void and non-void |
| 226 | + /// trailer type. |
186 | 227 | template <typename U = TrailerType> |
187 | 228 | typename std::enable_if<!std::is_void<U>::value, bool>::type |
188 | 229 | CheckTrailer(const FrameInfo& entry, CheckTrailerFct<TrailerType>& checkTrailer) const { |
@@ -200,10 +241,14 @@ class ForwardParser { |
200 | 241 | * @class ReverseParser |
201 | 242 | * Parser for a sequence of frames with header, trailer and variable payload. |
202 | 243 | * The size is expected to be part of the trailer, the parsing is thus in |
203 | | - * reverse direction. |
| 244 | + * reverse direction. Also the insert callback is called with the entries |
| 245 | + * starting form the end of the buffer. |
| 246 | + * TODO: an easy extension can be to reverse the order of the inserts, meaning |
| 247 | + * that the entries are read from the beginning. |
204 | 248 | * |
205 | 249 | * Usage: |
206 | | - * ReverseParser<SomeHeaderType, SomeTrailerType> SomeParser; |
| 250 | + * <pre> |
| 251 | + * using SomeParser = ReverseParser<SomeHeaderType, SomeTrailerType>; |
207 | 252 | * SomeParser parser; |
208 | 253 | * std::vector<typename SomeParser::FrameInfo> frames; |
209 | 254 | * parser.parse(ptr, size, |
@@ -226,6 +271,7 @@ class ForwardParser { |
226 | 271 | * return true; |
227 | 272 | * } |
228 | 273 | * ) |
| 274 | + * </pre> |
229 | 275 | */ |
230 | 276 | template<typename HeaderT, typename TrailerT> |
231 | 277 | class ReverseParser { |
@@ -234,6 +280,7 @@ class ReverseParser { |
234 | 280 | using TrailerType = TrailerT; |
235 | 281 | using PayloadType = unsigned char; |
236 | 282 |
|
| 283 | + /// @struct FrameInfo a compound of header, data, and trailer |
237 | 284 | struct FrameInfo { |
238 | 285 | using PtrT = const PayloadType*; |
239 | 286 |
|
@@ -249,11 +296,21 @@ class ReverseParser { |
249 | 296 | /// total length offset due to header and trailer |
250 | 297 | static const size_t totalOffset = headOffset + tailOffset; |
251 | 298 |
|
| 299 | + /// alias for callback checking the header, return true if the object |
| 300 | + /// is a valid header |
252 | 301 | using CheckHeaderFct = std::function<bool(const HeaderType&)>; |
| 302 | + /// alias for callback checking the trailer |
253 | 303 | using CheckTrailerFct = std::function<bool(const TrailerType&)>; |
| 304 | + /// alias for callback to get the complete frame size including header, |
| 305 | + /// trailer and the data |
254 | 306 | using GetFrameSizeFct = std::function<size_t(const TrailerType&)>; |
| 307 | + /// function callback to insert/handle one frame into, sequentially called |
| 308 | + /// for all frames if the whole block has a valid format |
255 | 309 | using InsertFct = std::function<bool(const FrameInfo&)>; |
256 | 310 |
|
| 311 | + /// Parse buffer of size bufferSize, requires callbacks to check header |
| 312 | + /// trailer, the frame size, and insert callback to handle a FrameInfo |
| 313 | + /// object. |
257 | 314 | template<typename InputType> |
258 | 315 | int parse(const InputType* buffer, size_t bufferSize, |
259 | 316 | CheckHeaderFct checkHeader, |
|