]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright Andrey Semashev 2007 - 2015. | |
3 | * Distributed under the Boost Software License, Version 1.0. | |
4 | * (See accompanying file LICENSE_1_0.txt or copy at | |
5 | * http://www.boost.org/LICENSE_1_0.txt) | |
6 | */ | |
7 | /*! | |
8 | * \file support/spirit_classic.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 19.07.2009 | |
11 | * | |
12 | * This header enables Boost.Spirit (classic) support for Boost.Log. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ | |
17 | ||
18 | #include <boost/mpl/bool.hpp> | |
19 | #include <boost/core/enable_if.hpp> | |
20 | #include <boost/log/detail/config.hpp> | |
21 | #include <boost/log/utility/functional/matches.hpp> | |
22 | ||
23 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
24 | #pragma once | |
25 | #endif | |
26 | ||
27 | #if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE) && !defined(BOOST_LOG_DOXYGEN_PASS) | |
28 | /* | |
29 | * As Boost.Log filters may be called in multiple threads concurrently, | |
30 | * this may lead to using Boost.Spirit parsers in a multithreaded context. | |
31 | * In order to protect parsers properly, BOOST_SPIRIT_THREADSAFE macro should | |
32 | * be defined. | |
33 | * | |
34 | * If we got here, it means that the user did not define that macro and we | |
35 | * have to define it ourselves. However, it may also lead to ODR violations | |
36 | * or even total ignorance of this macro, if the user has included Boost.Spirit | |
37 | * headers before including this header, or uses Boost.Spirit without the macro | |
38 | * in other translation units. The only reliable way to settle this problem is to | |
39 | * define the macro for the whole project (i.e. all translation units). | |
40 | */ | |
41 | #if defined(__GNUC__) | |
42 | #pragma message "Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide." | |
43 | #elif defined(_MSC_VER) | |
44 | #pragma message("Boost.Log: Boost.Spirit requires BOOST_SPIRIT_THREADSAFE macro to be defined if parsers are used in a multithreaded context. It is strongly recommended to define this macro project-wide.") | |
45 | #endif | |
46 | #define BOOST_SPIRIT_THREADSAFE 1 | |
47 | #endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_SPIRIT_THREADSAFE) | |
48 | ||
49 | #include <boost/spirit/include/classic_parser.hpp> | |
50 | ||
51 | #include <boost/log/detail/header.hpp> | |
52 | ||
53 | namespace boost { | |
54 | ||
55 | BOOST_LOG_OPEN_NAMESPACE | |
56 | ||
57 | namespace aux { | |
58 | ||
59 | //! This tag type is used if an expression is recognized as a Boost.Spirit.Classic expression | |
60 | struct boost_spirit_classic_expression_tag; | |
61 | ||
62 | //! The trait verifies if the type can be converted to a Boost.Spirit (classic) parser | |
63 | template< typename T > | |
64 | struct is_spirit_classic_parser | |
65 | { | |
66 | private: | |
67 | typedef char yes_type; | |
68 | struct no_type { char dummy[2]; }; | |
69 | ||
70 | template< typename U > | |
71 | static yes_type check_spirit_classic_parser(spirit::classic::parser< U > const&); | |
72 | static no_type check_spirit_classic_parser(...); | |
73 | static T& get_T(); | |
74 | ||
75 | public: | |
76 | enum { value = sizeof(check_spirit_classic_parser(get_T())) == sizeof(yes_type) }; | |
77 | typedef mpl::bool_< value > type; | |
78 | }; | |
79 | ||
80 | //! The metafunction detects the matching expression kind and returns a tag that is used to specialize \c match_traits | |
81 | template< typename ExpressionT > | |
82 | struct matching_expression_kind< ExpressionT, typename boost::enable_if_c< is_spirit_classic_parser< ExpressionT >::value >::type > | |
83 | { | |
84 | typedef boost_spirit_classic_expression_tag type; | |
85 | }; | |
86 | ||
87 | //! The matching function implementation | |
88 | template< typename ExpressionT > | |
89 | struct match_traits< ExpressionT, boost_spirit_classic_expression_tag > | |
90 | { | |
91 | typedef ExpressionT compiled_type; | |
92 | static compiled_type compile(ExpressionT const& expr) { return expr; } | |
93 | ||
94 | template< typename StringT > | |
95 | static bool matches(StringT const& str, ExpressionT const& expr) | |
96 | { | |
97 | typedef typename StringT::const_iterator const_iterator; | |
98 | spirit::classic::parse_info< const_iterator > info = | |
99 | spirit::classic::parse(str.begin(), str.end(), expr); | |
100 | return info.full; | |
101 | } | |
102 | }; | |
103 | ||
104 | } // namespace aux | |
105 | ||
106 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
107 | ||
108 | } // namespace boost | |
109 | ||
110 | #include <boost/log/detail/footer.hpp> | |
111 | ||
112 | #endif // BOOST_LOG_SUPPORT_SPIRIT_CLASSIC_HPP_INCLUDED_ |