COMMS
Template library intended to help with implementation of communication protocols.
process.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 - 2024 (C). Alex Robenko. All rights reserved.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
10 
11 #pragma once
12 
13 #include <type_traits>
14 #include <iterator>
15 
16 #include "comms/ErrorStatus.h"
17 #include "comms/iterator.h"
18 #include "comms/dispatch.h"
19 #include "comms/Message.h"
20 #include "comms/Assert.h"
21 #include "comms/MsgDispatcher.h"
22 #include "comms/details/detect.h"
23 #include "comms/details/process.h"
24 #include "comms/util/ScopeGuard.h"
26 
27 namespace comms
28 {
29 
51 template <typename TBufIter, typename TFrame, typename TMsg, typename... TExtraValues>
53  TBufIter& bufIter,
54  std::size_t len,
55  TFrame&& frame,
56  TMsg& msg,
57  TExtraValues... extraValues)
58 {
59  std::size_t consumed = 0U;
60  auto onExit =
61  comms::util::makeScopeGuard(
62  [&bufIter, &consumed]()
63  {
64  std::advance(bufIter, consumed);
65  });
66  static_cast<void>(onExit);
67 
68  while (consumed < len) {
69  auto begIter = comms::readIteratorFor(msg, bufIter + consumed);
70  auto iter = begIter;
71 
72  // Do the read
73  auto es = frame.read(msg, iter, len - consumed, extraValues...);
75  return es;
76  }
77 
79  // Something is not right with the data, remove one character and try again
80  ++consumed;
81  continue;
82  }
83 
84  consumed += static_cast<decltype(consumed)>(std::distance(begIter, iter));
85  return es;
86  }
87 
89 }
90 
118 template <typename TBufIter, typename TFrame, typename TMsg, typename THandler, typename... TExtraValues>
120  TBufIter& bufIter,
121  std::size_t len,
122  TFrame&& frame,
123  TMsg& msg,
124  THandler& handler,
125  TExtraValues... extraValues)
126 {
127  using LocalMsgIdType = details::ProcessMsgIdType<typename std::decay<decltype(msg)>::type>;
128  LocalMsgIdType id = LocalMsgIdType();
129  std::size_t idx = 0U;
130 
131  auto es =
133  bufIter,
134  len,
135  std::forward<TFrame>(frame),
136  msg,
139  extraValues...);
140 
141  if (es != comms::ErrorStatus::Success) {
142  return es;
143  }
144 
145  static_cast<void>(handler);
146  using FrameType = typename std::decay<decltype(frame)>::type;
147  using AllMessagesType = typename FrameType::AllMessages;
148  auto& msgObj = details::processMsgCastToMsgObj(msg);
149  comms::dispatchMsg<AllMessagesType>(id, idx, msgObj, handler);
150  return es;
151 }
152 
183 template <typename TDispatcher, typename TBufIter, typename TFrame, typename TMsg, typename THandler, typename... TExtraValues>
185  TBufIter& bufIter,
186  std::size_t len,
187  TFrame&& frame,
188  TMsg& msg,
189  THandler& handler,
190  TExtraValues... extraValues)
191 {
192  using LocalMsgIdType = details::ProcessMsgIdType<typename std::decay<decltype(msg)>::type>;
193  static_assert(!std::is_void<LocalMsgIdType>(), "Invalid type of msg param");
194 
195  LocalMsgIdType id = LocalMsgIdType();
196  std::size_t idx = 0U;
197 
198  auto es =
200  bufIter,
201  len,
202  std::forward<TFrame>(frame),
203  msg,
206  extraValues...);
207 
208  if (es != comms::ErrorStatus::Success) {
209  return es;
210  }
211 
212  using FrameType = typename std::decay<decltype(frame)>::type;
213  using AllMessagesType = typename FrameType::AllMessages;
214  static_assert(
215  comms::isMsgDispatcher<TDispatcher>(),
216  "TDispatcher is expected to be a variant of comms::MsgDispatcher");
217 
218  auto& msgObj = details::processMsgCastToMsgObj(msg);
219  TDispatcher::template dispatch<AllMessagesType>(id, idx, msgObj, handler);
220  return es;
221 }
222 
245 template <typename TBufIter, typename TFrame, typename THandler, typename... TExtraValues>
247  TBufIter bufIter,
248  std::size_t len,
249  TFrame&& frame,
250  THandler& handler)
251 {
252  std::size_t consumed = 0U;
253  using FrameType = typename std::decay<decltype(frame)>::type;
254  using MsgPtr = typename FrameType::MsgPtr;
255  while (consumed < len) {
256  auto begIter = bufIter + consumed;
257  auto iter = begIter;
258 
259  MsgPtr msg;
260  auto es = processSingleWithDispatch(iter, len - consumed, std::forward<TFrame>(frame), msg, handler);
261  consumed += static_cast<decltype(consumed)>(std::distance(begIter, iter));
263  break;
264  }
265  COMMS_ASSERT(consumed <= len);
266  }
267 
268  return consumed;
269 }
270 
294 template <typename TDispatcher, typename TBufIter, typename TFrame, typename THandler, typename... TExtraValues>
296  TBufIter bufIter,
297  std::size_t len,
298  TFrame&& frame,
299  THandler& handler)
300 {
301  std::size_t consumed = 0U;
302  using FrameType = typename std::decay<decltype(frame)>::type;
303  using MsgPtr = typename FrameType::MsgPtr;
304  while (consumed < len) {
305  auto begIter = bufIter + consumed;
306  auto iter = begIter;
307 
308  MsgPtr msg;
309  auto es = processSingleWithDispatchViaDispatcher<TDispatcher>(iter, len - consumed, std::forward<TFrame>(frame), msg, handler);
310  consumed += static_cast<decltype(consumed)>(std::distance(begIter, iter));
312  break;
313  }
314  COMMS_ASSERT(consumed <= len);
315  }
316 
317  return consumed;
318 }
319 
320 } // namespace comms
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition: Assert.h:170
This file contain definition of error statuses used by comms module.
Contains definition of Message object interface and various base classes for custom messages.
Contains definition of MsgDispatcher class which facilitates dispatching of message object to appropr...
Contains definition of comms::protocol::ProtocolLayerBase.
Contains definition of the "Scope Guard" idiom, see comms::util::ScopeGuard.
Contains extra logic to help with dispatching message types and objects.
Provides auxiliary functions for retrieving best type of iterator for read/write operations.
details::MsgIdRetriever< TId > msgId(TId &val)
Add "message ID" output parameter to protocol stack's (frame's) "read" operation.
Definition: ProtocolLayerBase.h:1588
details::MsgIndexRetriever msgIndex(std::size_t &val)
Add "message index" output parameter to protocol stack's (frame's) "read" operation.
Definition: ProtocolLayerBase.h:1626
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition: ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
std::size_t processAllWithDispatch(TBufIter bufIter, std::size_t len, TFrame &&frame, THandler &handler)
Process all available input and dispatch all created message objects to appropriate handling function...
Definition: process.h:246
auto readIteratorFor(TIter &&iter) -> decltype(details::ReadIteratorHelper<>::template get< TMessage >(std::forward< TIter >(iter)))
Create and initialise iterator for message read.
Definition: iterator.h:24
comms::ErrorStatus processSingle(TBufIter &bufIter, std::size_t len, TFrame &&frame, TMsg &msg, TExtraValues... extraValues)
Process input until first message is recognized and its object is created or missing data is reported...
Definition: process.h:52
comms::ErrorStatus processSingleWithDispatch(TBufIter &bufIter, std::size_t len, TFrame &&frame, TMsg &msg, THandler &handler, TExtraValues... extraValues)
Process input until first message is recognized, its object is created and dispatched to appropriate ...
Definition: process.h:119
comms::ErrorStatus processSingleWithDispatchViaDispatcher(TBufIter &bufIter, std::size_t len, TFrame &&frame, TMsg &msg, THandler &handler, TExtraValues... extraValues)
Process input until first message is recognized, its object is created and dispatched to appropriate ...
Definition: process.h:184
std::size_t processAllWithDispatchViaDispatcher(TBufIter bufIter, std::size_t len, TFrame &&frame, THandler &handler)
Process all available input and dispatch all created message objects to appropriate handling function...
Definition: process.h:295