| /* |
| * Copyright Andrey Semashev 2007 - 2015. |
| * Distributed under the Boost Software License, Version 1.0. |
| * (See accompanying file LICENSE_1_0.txt or copy at |
| * http://www.boost.org/LICENSE_1_0.txt) |
| */ |
| |
| #include <string> |
| #include <iostream> |
| #include <stdexcept> |
| #include <boost/smart_ptr/shared_ptr.hpp> |
| #include <boost/smart_ptr/make_shared_object.hpp> |
| #include <boost/lexical_cast.hpp> |
| #include <boost/phoenix.hpp> |
| #include <boost/log/core.hpp> |
| #include <boost/log/expressions.hpp> |
| #include <boost/log/attributes/attribute_name.hpp> |
| #include <boost/log/attributes/scoped_attribute.hpp> |
| #include <boost/log/sources/logger.hpp> |
| #include <boost/log/sources/record_ostream.hpp> |
| #include <boost/log/utility/value_ref.hpp> |
| #include <boost/log/utility/formatting_ostream.hpp> |
| #include <boost/log/utility/manipulators/add_value.hpp> |
| #include <boost/log/utility/setup/filter_parser.hpp> |
| #include <boost/log/utility/setup/common_attributes.hpp> |
| #include <boost/log/utility/setup/console.hpp> |
| |
| namespace logging = boost::log; |
| namespace attrs = boost::log::attributes; |
| namespace src = boost::log::sources; |
| namespace expr = boost::log::expressions; |
| namespace sinks = boost::log::sinks; |
| namespace keywords = boost::log::keywords; |
| |
| struct point |
| { |
| float m_x, m_y; |
| |
| point() : m_x(0.0f), m_y(0.0f) {} |
| point(float x, float y) : m_x(x), m_y(y) {} |
| }; |
| |
| bool operator== (point const& left, point const& right); |
| bool operator!= (point const& left, point const& right); |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p); |
| template< typename CharT, typename TraitsT > |
| std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p); |
| |
| const float epsilon = 0.0001f; |
| |
| bool operator== (point const& left, point const& right) |
| { |
| return (left.m_x - epsilon <= right.m_x && left.m_x + epsilon >= right.m_x) && |
| (left.m_y - epsilon <= right.m_y && left.m_y + epsilon >= right.m_y); |
| } |
| |
| bool operator!= (point const& left, point const& right) |
| { |
| return !(left == right); |
| } |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, point const& p) |
| { |
| if (strm.good()) |
| strm << "(" << p.m_x << ", " << p.m_y << ")"; |
| return strm; |
| } |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, point& p) |
| { |
| if (strm.good()) |
| { |
| CharT left_brace = static_cast< CharT >(0), comma = static_cast< CharT >(0), right_brace = static_cast< CharT >(0); |
| strm.setf(std::ios_base::skipws); |
| strm >> left_brace >> p.m_x >> comma >> p.m_y >> right_brace; |
| if (left_brace != '(' || comma != ',' || right_brace != ')') |
| strm.setstate(std::ios_base::failbit); |
| } |
| return strm; |
| } |
| |
| //[ example_extension_filter_parser_rectangle_definition |
| struct rectangle |
| { |
| point m_top_left, m_bottom_right; |
| }; |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, rectangle const& r); |
| template< typename CharT, typename TraitsT > |
| std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, rectangle& r); |
| //] |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, rectangle const& r) |
| { |
| if (strm.good()) |
| strm << "{" << r.m_top_left << " - " << r.m_bottom_right << "}"; |
| return strm; |
| } |
| |
| template< typename CharT, typename TraitsT > |
| std::basic_istream< CharT, TraitsT >& operator>> (std::basic_istream< CharT, TraitsT >& strm, rectangle& r) |
| { |
| if (strm.good()) |
| { |
| CharT left_brace = static_cast< CharT >(0), dash = static_cast< CharT >(0), right_brace = static_cast< CharT >(0); |
| strm.setf(std::ios_base::skipws); |
| strm >> left_brace >> r.m_top_left >> dash >> r.m_bottom_right >> right_brace; |
| if (left_brace != '{' || dash != '-' || right_brace != '}') |
| strm.setstate(std::ios_base::failbit); |
| } |
| return strm; |
| } |
| |
| |
| //[ example_extension_custom_filter_factory_with_custom_rel |
| // The function checks if the point is inside the rectangle |
| bool is_in_rectangle(logging::value_ref< point > const& p, rectangle const& r) |
| { |
| if (p) |
| { |
| return p->m_x >= r.m_top_left.m_x && p->m_x <= r.m_bottom_right.m_x && |
| p->m_y >= r.m_top_left.m_y && p->m_y <= r.m_bottom_right.m_y; |
| } |
| return false; |
| } |
| |
| // Custom point filter factory |
| class point_filter_factory : |
| public logging::filter_factory< char > |
| { |
| public: |
| logging::filter on_exists_test(logging::attribute_name const& name) |
| { |
| return expr::has_attr< point >(name); |
| } |
| |
| logging::filter on_equality_relation(logging::attribute_name const& name, string_type const& arg) |
| { |
| return expr::attr< point >(name) == boost::lexical_cast< point >(arg); |
| } |
| |
| logging::filter on_inequality_relation(logging::attribute_name const& name, string_type const& arg) |
| { |
| return expr::attr< point >(name) != boost::lexical_cast< point >(arg); |
| } |
| |
| logging::filter on_custom_relation(logging::attribute_name const& name, string_type const& rel, string_type const& arg) |
| { |
| if (rel == "is_in_rectangle") |
| { |
| return boost::phoenix::bind(&is_in_rectangle, expr::attr< point >(name), boost::lexical_cast< rectangle >(arg)); |
| } |
| throw std::runtime_error("Unsupported filter relation: " + rel); |
| } |
| }; |
| |
| void init_factories() |
| { |
| //<- |
| logging::register_simple_formatter_factory< point, char >("Coordinates"); |
| //-> |
| logging::register_filter_factory("Coordinates", boost::make_shared< point_filter_factory >()); |
| } |
| //] |
| |
| void init_logging() |
| { |
| init_factories(); |
| |
| logging::add_console_log |
| ( |
| std::clog, |
| keywords::filter = "%Coordinates% is_in_rectangle \"{(0, 0) - (20, 20)}\"", |
| keywords::format = "%TimeStamp% %Coordinates% %Message%" |
| ); |
| |
| logging::add_common_attributes(); |
| } |
| |
| int main(int, char*[]) |
| { |
| init_logging(); |
| |
| src::logger lg; |
| |
| // We have to use scoped attributes in order coordinates to be passed to filters |
| { |
| BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(10, 10)); |
| BOOST_LOG(lg) << "Hello, world with coordinates (10, 10)!"; |
| } |
| { |
| BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Coordinates", point(50, 50)); |
| BOOST_LOG(lg) << "Hello, world with coordinates (50, 50)!"; // this message will be suppressed by filter |
| } |
| |
| return 0; |
| } |