diff --git a/include/rosa/core/MessageMatcher.hpp b/include/rosa/core/MessageMatcher.hpp index b3d6b2a..dcda87e 100644 --- a/include/rosa/core/MessageMatcher.hpp +++ b/include/rosa/core/MessageMatcher.hpp @@ -1,168 +1,168 @@ /******************************************************************************* * * 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 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 struct MessageMatcher; // Definition of MessageMatcher for non-empty lists of types, like Message // itself. template struct MessageMatcher> { // Type Token associated with the give TypeList. static constexpr Token T = TypeToken::Value; // Tells if stored values in Msg are matching types given as // TypeList, 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 extractedValues(const Message &Msg) noexcept; }; // Convenience template alias turning a list of types into a TypeList for // MessageMatcher. template using MsgMatcher = MessageMatcher>; // Nested namespace with implementation for features of MessageMatcher, // consider it private. namespace { // Helper struct implementing type-checking and value extraction for // MessageMatcher. template struct MessageMatcherImpl; // Specialization handling the empty list of types. template <> struct MessageMatcherImpl { 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 struct MessageMatcherImpl, 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(Pos) && Msg.getValueAt(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>::doesStronglyMatchFrom(Msg, Pos + 1); } static inline std::tuple &, 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::Value), MessageMatcherImpl>::extractedValuesFrom(Msg, Pos + 1)); } }; // Specialization handling an regular builtin type (not an AtomConstant) in the // head. template struct MessageMatcherImpl> { 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(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>::doesStronglyMatchFrom(Msg, Pos + 1); } static inline std::tuple 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(Pos)), MessageMatcherImpl>::extractedValuesFrom(Msg, Pos + 1)); } }; } // End namespace template bool MessageMatcher>::doesStronglyMatch( const Message &Msg) noexcept { - // NOTE: Fail quick on the size and T, then match against list with squashed - // integers as Tokens are generated. - return (1 + sizeof...(Ts)) == Msg.Size && T == Msg.T && + // NOTE: Fail quick on T, then match against list with squashed integers the + // way Tokens are generated. + return T == Msg.T && MessageMatcherImpl>::Type>::doesStronglyMatchFrom(Msg, 0); } template std::tuple MessageMatcher>::extractedValues( const Message &Msg) noexcept { ASSERT(doesStronglyMatch(Msg)); // NOTE: Match against list with squashed integers as Tokens are generated. return MessageMatcherImpl>::Type>::extractedValuesFrom(Msg, 0); } } // End namespace rosa #endif // ROSA_CORE_MESSAGEMATCHER_HPP