Page MenuHomePhorge

MessageMatcher.hpp
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

MessageMatcher.hpp

/*******************************************************************************
*
* File: MessageMatcher.hpp
*
* Contents: Implementation of MessageMatcher.
*
* Copyright 2017
*
* Author: David Juhasz (david.juhasz@tuwien.ac.at)
*
******************************************************************************/
#ifndef ROSA_CORE_MESSAGEMATCHER_HPP
#define ROSA_CORE_MESSAGEMATCHER_HPP
#include "rosa/core/Message.hpp"
#include <tuple>
namespace rosa {
// Template class with static functions type-checking a Message instance and
// extracting stored values from Message instsances into std::tuple instances
// with matching type arguments.
template <typename List> struct MessageMatcher;
// Definition of MessageMatcher for non-empty lists of types, like Message
// itself.
template <typename T, typename... Ts>
struct MessageMatcher<TypeList<T, Ts...>> {
// Tells if stored values in Msg are matching types given as
// TypeList<T, Ts...>, considering exact AtomConstants instead of AtomValues.
static inline bool doesStronglyMatch(const Message &Msg) noexcept;
// Gives a std::tuple with references to values stored in a type-matching Msg.
// PRE: doesStronglyMatch(Msg)
static inline std::tuple<const T &, const Ts &...>
extractedValues(const Message &Msg) noexcept;
};
// Convenience template alias turning a list of types into a TypeList for
// MessageMatcher.
template <typename T, typename...Ts>
using MsgMatcher = MessageMatcher<TypeList<T, Ts...>>;
// Nested namespace with implementation for features of MessageMatcher,
// consider it private.
namespace {
// Helper struct implementing type-checking and value extraction for
// MessageMatcher.
template <typename List> struct MessageMatcherImpl;
// Specialization handling the empty list of types.
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 handling an 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.getValueAt<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));
}
};
// Specialization handling an regular builtin type (not an AtomConstant) 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.getValueAt<T>(Pos)),
MessageMatcherImpl<TypeList<Ts...>>::extractedValuesFrom(Msg, Pos + 1));
}
};
} // End namespace
template <typename T, typename... Ts>
bool MessageMatcher<TypeList<T, Ts...>>::doesStronglyMatch(
const Message &Msg) noexcept {
// NOTE: Fail quick on the size.
return (1 + sizeof...(Ts)) == Msg.size() &&
MessageMatcherImpl<TypeList<T, Ts...>>::doesStronglyMatchFrom(Msg, 0);
}
template <typename T, typename... Ts>
std::tuple<const T &, const Ts &...>
MessageMatcher<TypeList<T, Ts...>>::extractedValues(
const Message &Msg) noexcept {
ASSERT(doesStronglyMatch(Msg));
return MessageMatcherImpl<TypeList<T, Ts...>>::extractedValuesFrom(Msg, 0);
}
} // End namespace rosa
#endif // ROSA_CORE_MESSAGEMATCHER_HPP

File Metadata

Mime Type
text/x-c++
Expires
Sat, Aug 1, 10:53 PM (23 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
343015
Default Alt Text
MessageMatcher.hpp (5 KB)

Event Timeline