/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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; }