Page MenuHomePhorge

MessageMatcher.hpp
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

MessageMatcher.hpp

/***************************************************************************//**
*
* \file rosa/core/MessageMatcher.hpp
*
* \author David Juhasz (david.juhasz@tuwien.ac.at)
*
* \date 2017
*
* \brief Facilities for checking and matching types of values stored in
* `rosa::Message` instances.
*
******************************************************************************/
#ifndef ROSA_CORE_MESSAGEMATCHER_HPP
#define ROSA_CORE_MESSAGEMATCHER_HPP
#include "rosa/core/Message.hpp"
#include <tuple>
namespace rosa {
/// Provides features to type-check a `rosa::Message` instance and extract
/// stored values from it into an `std::tuple` instance with matching type
/// arguments.
///
/// \tparam List `rosa::TypeList` to check the stored values against
template <typename List> struct MessageMatcher;
/// Definition of `rosa::MessageMatcher` for non-empty lists of types, like
/// `rosa::Message` itself.
///
/// \tparam Type first mandatory type
/// \tparam Types any further types
template <typename Type, typename... Types>
struct MessageMatcher<TypeList<Type, Types...>> {
/// `rosa::Token` associated to the give `rosa::TypeList`.
static constexpr Token T = TypeToken<Type, Types...>::Value;
/// Tells if the values stored in a `rosa::Message` instance are matching
/// types given as `rosa::TypeList<T, Types...>`, considering
/// `rosa::AtomConstant` instead of `rosa::AtomValue`.
///
/// \param Msg `Message` to match
///
/// \return whether the types of values stored in `Msg` matches
/// `rosa::TypeList<Type, Types...>`
static inline bool doesStronglyMatch(const Message &Msg) noexcept;
/// Gives a `std::tuple` with references to the values stored in a
/// type-matching instance of `rosa::Message`.
///
/// \param Msg `Message` to extract values from
///
/// \return `tuple` with references to the values stored in `Msg`
///
/// \pre Types of the values stored in `Msg` matches
/// `rosa::TypeList<Type, Types...>`:\code
/// doesStronglyMatch(Msg)
/// \endcode
static inline std::tuple<const Type &, const Types &...>
extractedValues(const Message &Msg) noexcept;
};
/// Turns a list of types into a `rosa::TypeList` for `rosa::MessageMatcher`.
template <typename Type, typename...Types>
using MsgMatcher = MessageMatcher<TypeList<Type, Types...>>;
/// Nested namespace with implementation for features of `rosa::MessageMatcher`,
/// consider it private.
namespace {
/// \defgroup MessageMatcherImpl
///
/// An implementation of type-checking and value extraction for
/// `rosa::MessageMatcher`.
///
///@{
/// Template declaration of `rosa::MessageMatcherImpl.
///
/// \tparam List `rosa::TypeList` to match against
template <typename List> struct MessageMatcherImpl;
/// Specialization for `rosa::EmptyTypeList`.
template <> struct MessageMatcherImpl<EmptyTypeList> {
static inline bool doesStronglyMatchFrom(const Message &Msg,
const size_t Pos) noexcept {
// Matching EmptyTypeList only if reached the end of the stored types.
return Pos == Msg.Size;
}
static inline std::tuple<> extractedValuesFrom(const Message &Msg,
const size_t Pos) noexcept {
// It is valid to extract an empty list only if we reached the end of
// stored values.
ASSERT(doesStronglyMatchFrom(Msg, Pos));
return std::tie();
}
};
/// Specialization for `rosa::AtomValue` in the head.
template <AtomValue V, typename... Ts>
struct MessageMatcherImpl<TypeList<AtomConstant<V>, Ts...>> {
static inline bool doesHeadStronglyMatchAt(const Message &Msg,
const size_t Pos) noexcept {
// Matching an AtomConstant in the head if there is a type stored at Pos,
// the stored type is AtomValue, and the corresponding value matches the
// AtomValue V.
return Pos < Msg.Size && Msg.isTypeAt<AtomValue>(Pos) &&
Msg.valueAt<AtomValue>(Pos) == V;
}
static inline bool doesStronglyMatchFrom(const Message &Msg,
const size_t Pos) noexcept {
// Matching a non-empty list if the head is matching and the rest of the
// list is matching.
return doesHeadStronglyMatchAt(Msg, Pos) &&
MessageMatcherImpl<TypeList<Ts...>>::doesStronglyMatchFrom(Msg,
Pos + 1);
}
static inline std::tuple<const AtomConstant<V> &, const Ts &...>
extractedValuesFrom(const Message &Msg, const size_t Pos) noexcept {
// Extracting for a non-empty list with a matching AtomConstant in the head
// by getting the encoded AtomConstant and concatenating it with values
// extracted for the rest of the list.
ASSERT(doesHeadStronglyMatchAt(Msg, Pos));
return std::tuple_cat(
std::tie(AtomConstant<V>::Value),
MessageMatcherImpl<TypeList<Ts...>>::extractedValuesFrom(Msg, Pos + 1));
}
};
/// Definition for the general case when a regular built-in type (not a
/// `rosa::AtomConstant`) is in the head.
template <typename T, typename... Ts>
struct MessageMatcherImpl<TypeList<T, Ts...>> {
static inline bool doesHeadStronglyMatchAt(const Message &Msg,
const size_t Pos) noexcept {
// Matching the head if there is a type stored at Pos, and the stored type
// is T.
return Pos < Msg.Size && Msg.isTypeAt<T>(Pos);
}
static inline bool doesStronglyMatchFrom(const Message &Msg,
const size_t Pos) noexcept {
// Matching a non-empty list if the head is matching and the rest of the
// list is matching.
return doesHeadStronglyMatchAt(Msg, Pos) &&
MessageMatcherImpl<TypeList<Ts...>>::doesStronglyMatchFrom(Msg,
Pos + 1);
}
static inline std::tuple<const T &, const Ts &...>
extractedValuesFrom(const Message &Msg, const size_t Pos) noexcept {
// Extracting for a non-empty list with a matching head by getting the
// value for the head and concatenating it with values extracted for the
// rest of the list.
ASSERT(doesHeadStronglyMatchAt(Msg, Pos));
return std::tuple_cat(
std::tie(Msg.valueAt<T>(Pos)),
MessageMatcherImpl<TypeList<Ts...>>::extractedValuesFrom(Msg, Pos + 1));
}
};
///@}
} // End namespace
template <typename Type, typename... Ts>
bool MessageMatcher<TypeList<Type, Ts...>>::doesStronglyMatch(
const Message &Msg) noexcept {
// \note Fail quick on T, then match against list with squashed integers the
// way `rosa::Token` is generated.
return T == Msg.T &&
MessageMatcherImpl<typename SquashedTypeList<
TypeList<Type, Ts...>>::Type>::doesStronglyMatchFrom(Msg, 0);
}
template <typename Type, typename... Ts>
std::tuple<const Type &, const Ts &...>
MessageMatcher<TypeList<Type, Ts...>>::extractedValues(
const Message &Msg) noexcept {
ASSERT(doesStronglyMatch(Msg));
// \note Match against a list with squashed integers as `rosa::Token` is
// generated.
return MessageMatcherImpl<typename SquashedTypeList<
TypeList<Type, Ts...>>::Type>::extractedValuesFrom(Msg, 0);
}
} // End namespace rosa
#endif // ROSA_CORE_MESSAGEMATCHER_HPP

File Metadata

Mime Type
text/x-c++
Expires
Sat, Aug 29, 5:13 PM (9 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
328130
Default Alt Text
MessageMatcher.hpp (7 KB)

Event Timeline