From 70debc533b081ccc77855ba24ad74ef8e04f051d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 9 Aug 2016 04:20:49 +0300 Subject: [PATCH] Changed the max_size decorator so that the overflow marker length is included into the size limit. The max_size method on the stream buffer will now attempt to truncate the attached string on the character boundary. Fixed character boundary detection for multibyte encodings. Clean up the overflow flag and the max size limit after the formatter has completed. Added a test for the max_size decorator. Cleaned up some includes and reduced the dependency on Boost.Thread. --- example/doc/core_core_manual.cpp | 2 +- example/doc/extension_record_tagger.cpp | 2 +- example/doc/sources_net_connection.cpp | 2 +- example/doc/sources_severity.cpp | 2 +- example/doc/tutorial_logging.cpp | 2 +- .../log/attributes/attribute_value_impl.hpp | 2 +- include/boost/log/attributes/constant.hpp | 2 +- .../boost/log/attributes/mutable_constant.hpp | 2 +- .../boost/log/attributes/scoped_attribute.hpp | 2 +- .../log/detail/attachable_sstream_buf.hpp | 13 +- include/boost/log/detail/enqueued_record.hpp | 2 +- include/boost/log/detail/light_function.hpp | 2 +- include/boost/log/detail/locks.hpp | 31 ++- include/boost/log/detail/threadsafe_queue.hpp | 2 +- include/boost/log/expressions/filter.hpp | 2 +- include/boost/log/expressions/formatter.hpp | 2 +- include/boost/log/expressions/formatters.hpp | 1 + .../expressions/formatters/char_decorator.hpp | 2 +- .../log/expressions/formatters/date_time.hpp | 2 +- .../formatters/max_size_decorator.hpp | 54 +++-- .../expressions/formatters/named_scope.hpp | 2 +- .../expressions/formatters/wrap_formatter.hpp | 2 +- .../boost/log/sinks/basic_sink_frontend.hpp | 41 ++-- include/boost/log/sources/basic_logger.hpp | 2 +- include/boost/log/sources/channel_feature.hpp | 2 +- .../log/sources/exception_handler_feature.hpp | 2 +- include/boost/log/sources/record_ostream.hpp | 2 +- .../boost/log/sources/severity_feature.hpp | 2 +- include/boost/log/support/date_time.hpp | 2 +- include/boost/log/utility/strictest_lock.hpp | 5 + src/core.cpp | 2 +- src/format_parser.cpp | 2 +- src/named_scope_format_parser.cpp | 2 +- src/posix/object_name.cpp | 2 +- src/setup/filter_parser.cpp | 2 +- src/setup/formatter_parser.cpp | 2 +- src/setup/settings_parser.cpp | 2 +- src/windows/object_name.cpp | 2 +- test/common/make_record.hpp | 2 +- test/run/core.cpp | 2 +- test/run/form_max_size_decor.cpp | 185 ++++++++++++++++++ test/run/util_ipc_object_name.cpp | 2 +- test/run/util_ipc_reliable_mq.cpp | 2 +- 43 files changed, 331 insertions(+), 71 deletions(-) create mode 100644 test/run/form_max_size_decor.cpp diff --git a/example/doc/core_core_manual.cpp b/example/doc/core_core_manual.cpp index 874de33..71f6a0b 100644 --- a/example/doc/core_core_manual.cpp +++ b/example/doc/core_core_manual.cpp @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include diff --git a/example/doc/extension_record_tagger.cpp b/example/doc/extension_record_tagger.cpp index 1c1d627..99cc7cd 100644 --- a/example/doc/extension_record_tagger.cpp +++ b/example/doc/extension_record_tagger.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/example/doc/sources_net_connection.cpp b/example/doc/sources_net_connection.cpp index 59c950b..ef7ce35 100644 --- a/example/doc/sources_net_connection.cpp +++ b/example/doc/sources_net_connection.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/example/doc/sources_severity.cpp b/example/doc/sources_severity.cpp index 8741524..4110fb7 100644 --- a/example/doc/sources_severity.cpp +++ b/example/doc/sources_severity.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/example/doc/tutorial_logging.cpp b/example/doc/tutorial_logging.cpp index 31fe887..fd37f29 100644 --- a/example/doc/tutorial_logging.cpp +++ b/example/doc/tutorial_logging.cpp @@ -5,7 +5,7 @@ * http://www.boost.org/LICENSE_1_0.txt) */ -#include +#include #include #include #include diff --git a/include/boost/log/attributes/attribute_value_impl.hpp b/include/boost/log/attributes/attribute_value_impl.hpp index b21091e..e18015b 100644 --- a/include/boost/log/attributes/attribute_value_impl.hpp +++ b/include/boost/log/attributes/attribute_value_impl.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/attributes/constant.hpp b/include/boost/log/attributes/constant.hpp index 1e9a036..f10b0a7 100644 --- a/include/boost/log/attributes/constant.hpp +++ b/include/boost/log/attributes/constant.hpp @@ -16,7 +16,7 @@ #define BOOST_LOG_ATTRIBUTES_CONSTANT_HPP_INCLUDED_ #include -#include +#include #include #include #include diff --git a/include/boost/log/attributes/mutable_constant.hpp b/include/boost/log/attributes/mutable_constant.hpp index 52356b4..6ff76dd 100644 --- a/include/boost/log/attributes/mutable_constant.hpp +++ b/include/boost/log/attributes/mutable_constant.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/attributes/scoped_attribute.hpp b/include/boost/log/attributes/scoped_attribute.hpp index 0e49581..88dd218 100644 --- a/include/boost/log/attributes/scoped_attribute.hpp +++ b/include/boost/log/attributes/scoped_attribute.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/detail/attachable_sstream_buf.hpp b/include/boost/log/detail/attachable_sstream_buf.hpp index dd70d0e..3608bb1 100644 --- a/include/boost/log/detail/attachable_sstream_buf.hpp +++ b/include/boost/log/detail/attachable_sstream_buf.hpp @@ -150,7 +150,8 @@ public: { if (m_storage_state.storage && m_storage_state.storage->size() > m_storage_state.max_size) { - m_storage_state.storage->resize(m_storage_state.max_size); + const size_type len = length_until_boundary(m_storage_state.storage->c_str(), m_storage_state.storage->size(), m_storage_state.max_size); + m_storage_state.storage->resize(len); m_storage_state.overflow = true; } } @@ -186,7 +187,7 @@ public: else { // We have to find out where the last character that fits before the limit ends - left = length_until_boundary(s, n, left, mpl::bool_< sizeof(char_type) == 1u >()); + left = length_until_boundary(s, n, left); m_storage_state.storage->append(s, left); m_storage_state.overflow = true; return left; @@ -273,11 +274,17 @@ protected: return static_cast< std::streamsize >(this->append(s, static_cast< size_type >(n))); } + //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size + size_type length_until_boundary(const char_type* s, size_type n, size_type max_size) const + { + return length_until_boundary(s, n, max_size, mpl::bool_< sizeof(char_type) == 1u >());; + } + //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, mpl::true_) const { std::locale loc = this->getloc(); - std::codecvt< char_type, char, std::mbstate_t > const& fac = std::use_facet< std::codecvt< char_type, char, std::mbstate_t > >(loc); + std::codecvt< wchar_t, char, std::mbstate_t > const& fac = std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc); std::mbstate_t mbs = std::mbstate_t(); return static_cast< size_type >(fac.length(mbs, s, s + max_size, ~static_cast< std::size_t >(0u))); } diff --git a/include/boost/log/detail/enqueued_record.hpp b/include/boost/log/detail/enqueued_record.hpp index ef63777..f482136 100644 --- a/include/boost/log/detail/enqueued_record.hpp +++ b/include/boost/log/detail/enqueued_record.hpp @@ -18,7 +18,7 @@ #define BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ #include -#include +#include #include #include #include diff --git a/include/boost/log/detail/light_function.hpp b/include/boost/log/detail/light_function.hpp index 7d4efc9..0835772 100644 --- a/include/boost/log/detail/light_function.hpp +++ b/include/boost/log/detail/light_function.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/detail/locks.hpp b/include/boost/log/detail/locks.hpp index 99bc7e1..224d8e5 100644 --- a/include/boost/log/detail/locks.hpp +++ b/include/boost/log/detail/locks.hpp @@ -32,6 +32,8 @@ namespace boost { template< typename > class lock_guard; template< typename > +class shared_lock_guard; +template< typename > class shared_lock; template< typename > class upgrade_lock; @@ -92,6 +94,25 @@ struct is_shared_lockable enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) }; }; +//! A scope guard that automatically unlocks the mutex on destruction +template< typename MutexT > +struct exclusive_auto_unlocker +{ + explicit exclusive_auto_unlocker(MutexT& m) BOOST_NOEXCEPT : m_Mutex(m) + { + } + ~exclusive_auto_unlocker() + { + m_Mutex.unlock(); + } + + BOOST_DELETED_FUNCTION(exclusive_auto_unlocker(exclusive_auto_unlocker const&)) + BOOST_DELETED_FUNCTION(exclusive_auto_unlocker& operator= (exclusive_auto_unlocker const&)) + +protected: + MutexT& m_Mutex; +}; + //! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread. template< typename MutexT > struct exclusive_lock_guard @@ -105,9 +126,8 @@ struct exclusive_lock_guard m_Mutex.unlock(); } -private: - exclusive_lock_guard(exclusive_lock_guard const&); - exclusive_lock_guard& operator= (exclusive_lock_guard const&); + BOOST_DELETED_FUNCTION(exclusive_lock_guard(exclusive_lock_guard const&)) + BOOST_DELETED_FUNCTION(exclusive_lock_guard& operator= (exclusive_lock_guard const&)) private: MutexT& m_Mutex; @@ -126,9 +146,8 @@ struct shared_lock_guard m_Mutex.unlock_shared(); } -private: - shared_lock_guard(shared_lock_guard const&); - shared_lock_guard& operator= (shared_lock_guard const&); + BOOST_DELETED_FUNCTION(shared_lock_guard(shared_lock_guard const&)) + BOOST_DELETED_FUNCTION(shared_lock_guard& operator= (shared_lock_guard const&)) private: MutexT& m_Mutex; diff --git a/include/boost/log/detail/threadsafe_queue.hpp b/include/boost/log/detail/threadsafe_queue.hpp index 2ab2172..b8b3dbe 100644 --- a/include/boost/log/detail/threadsafe_queue.hpp +++ b/include/boost/log/detail/threadsafe_queue.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/expressions/filter.hpp b/include/boost/log/expressions/filter.hpp index 2d1d188..1e53f5c 100644 --- a/include/boost/log/expressions/filter.hpp +++ b/include/boost/log/expressions/filter.hpp @@ -16,7 +16,7 @@ #define BOOST_LOG_EXPRESSIONS_FILTER_HPP_INCLUDED_ #include -#include +#include #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #include diff --git a/include/boost/log/expressions/formatter.hpp b/include/boost/log/expressions/formatter.hpp index 56aa1d2..bc80dfa 100644 --- a/include/boost/log/expressions/formatter.hpp +++ b/include/boost/log/expressions/formatter.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #include diff --git a/include/boost/log/expressions/formatters.hpp b/include/boost/log/expressions/formatters.hpp index 1d3f4ed..f85cb79 100644 --- a/include/boost/log/expressions/formatters.hpp +++ b/include/boost/log/expressions/formatters.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/log/expressions/formatters/char_decorator.hpp b/include/boost/log/expressions/formatters/char_decorator.hpp index 9c29622..50f6391 100644 --- a/include/boost/log/expressions/formatters/char_decorator.hpp +++ b/include/boost/log/expressions/formatters/char_decorator.hpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/expressions/formatters/date_time.hpp b/include/boost/log/expressions/formatters/date_time.hpp index 72029f0..a51f843 100644 --- a/include/boost/log/expressions/formatters/date_time.hpp +++ b/include/boost/log/expressions/formatters/date_time.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/expressions/formatters/max_size_decorator.hpp b/include/boost/log/expressions/formatters/max_size_decorator.hpp index fe70bef..f428812 100644 --- a/include/boost/log/expressions/formatters/max_size_decorator.hpp +++ b/include/boost/log/expressions/formatters/max_size_decorator.hpp @@ -17,9 +17,10 @@ #include #include +#include #include #include -#include +#include #include #include #include @@ -100,6 +101,7 @@ public: max_size_decorator_output_terminal(LeftT const& left, subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) : m_left(left), m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker) { + BOOST_ASSERT(overflow_marker.size() <= max_size); } /*! * Copy constructor @@ -136,10 +138,20 @@ public: if (strm.rdbuf()->storage_overflow()) { - // Append overflow marker - strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size()); - strm.rdbuf()->storage_overflow(false); - strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); + if (!m_overflow_marker.empty()) + { + // Free up space for the overflow marker + strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size()); + + // Append the marker + strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size()); + strm.rdbuf()->storage_overflow(false); + strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); + } + else + { + strm.rdbuf()->storage_overflow(false); + } } // Restore the original size limit @@ -183,10 +195,20 @@ public: if (strm.rdbuf()->storage_overflow()) { - // Append overflow marker - strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size()); - strm.rdbuf()->storage_overflow(false); - strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); + if (!m_overflow_marker.empty()) + { + // Free up space for the overflow marker + strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size()); + + // Append the marker + strm.rdbuf()->max_size(strm.rdbuf()->storage()->max_size()); + strm.rdbuf()->storage_overflow(false); + strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); + } + else + { + strm.rdbuf()->storage_overflow(false); + } } // Restore the original size limit @@ -213,8 +235,8 @@ public: * of the strings generated by other formatters. * * The \c max_size_decorator_terminal class aggregates the formatter being decorated, the maximum string length - * it can produce and an optional truncation marker string, which will get appended if the limit is exceeded. Note that - * the marker length is not accounted for by the limit. + * it can produce and an optional truncation marker string, which will be put at the end of the output if the limit is exceeded. Note that + * the marker length is included in the limit and as such must not exceed it. * The \c max_size_decorator_terminal class is a formatter itself, so it can be used to construct * more complex formatters, including nesting decorators. */ @@ -258,6 +280,7 @@ public: max_size_decorator_terminal(subactor_type const& sub, size_type max_size, string_type const& overflow_marker = string_type()) : m_subactor(sub), m_max_size(max_size), m_overflow_marker(overflow_marker) { + BOOST_ASSERT(overflow_marker.size() <= max_size); } /*! * Copy constructor @@ -320,8 +343,9 @@ public: // Flush the buffered characters and see of overflow happened strm.flush(); - if (strm.rdbuf()->storage_overflow()) + if (strm.rdbuf()->storage_overflow() && !m_overflow_marker.empty()) { + strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size()); strm.rdbuf()->max_size(str.max_size()); strm.rdbuf()->storage_overflow(false); strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); @@ -362,6 +386,7 @@ public: if (strm.rdbuf()->storage_overflow()) { + strm.rdbuf()->max_size(strm.rdbuf()->max_size() - m_overflow_marker.size()); strm.rdbuf()->max_size(str.max_size()); strm.rdbuf()->storage_overflow(false); strm.rdbuf()->append(m_overflow_marker.data(), m_overflow_marker.size()); @@ -439,6 +464,7 @@ public: explicit max_size_decorator_gen(size_type max_size, string_type const& overflow_marker = string_type()) : m_max_size(max_size), m_overflow_marker(overflow_marker) { + BOOST_ASSERT(overflow_marker.size() <= max_size); } template< typename SubactorT > @@ -473,7 +499,7 @@ BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_ * \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded. Must be * a non-null pointer to a zero-terminated string. * - * \note The \a overflow_marker length is not included in the \a max_size limit. + * \pre The \a overflow_marker length must not exceed the \a max_size limit. */ template< typename CharT > BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, const CharT* overflow_marker) @@ -488,7 +514,7 @@ BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_ * \param max_size The maximum number of characters (i.e. string element objects) that the decorated formatter can produce. * \param overflow_marker The marker string which is appended to the output if the \a max_size limit is exceeded. * - * \note The \a overflow_marker length is not included in the \a max_size limit. + * \pre The \a overflow_marker length must not exceed the \a max_size limit. */ template< typename CharT > BOOST_FORCEINLINE aux::max_size_decorator_gen< CharT > max_size_decor(std::size_t max_size, std::basic_string< CharT > const& overflow_marker) diff --git a/include/boost/log/expressions/formatters/named_scope.hpp b/include/boost/log/expressions/formatters/named_scope.hpp index 0f3b9c7..a2c6615 100644 --- a/include/boost/log/expressions/formatters/named_scope.hpp +++ b/include/boost/log/expressions/formatters/named_scope.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/expressions/formatters/wrap_formatter.hpp b/include/boost/log/expressions/formatters/wrap_formatter.hpp index a5df456..81cc322 100644 --- a/include/boost/log/expressions/formatters/wrap_formatter.hpp +++ b/include/boost/log/expressions/formatters/wrap_formatter.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/sinks/basic_sink_frontend.hpp b/include/boost/log/sinks/basic_sink_frontend.hpp index 965451c..3686bc5 100644 --- a/include/boost/log/sinks/basic_sink_frontend.hpp +++ b/include/boost/log/sinks/basic_sink_frontend.hpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -29,7 +28,6 @@ #if !defined(BOOST_LOG_NO_THREADS) #include #include -#include #include #include #endif // !defined(BOOST_LOG_NO_THREADS) @@ -186,13 +184,10 @@ protected: bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) { #if !defined(BOOST_LOG_NO_THREADS) - unique_lock< BackendMutexT > lock; try { - unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); - if (!tmp_lock.owns_lock()) + if (!backend_mutex.try_lock()) return false; - lock.swap(tmp_lock); } catch (thread_interrupted&) { @@ -206,6 +201,8 @@ protected: this->exception_handler()(); return false; } + + boost::log::aux::exclusive_auto_unlocker< BackendMutexT > unlocker(backend_mutex); #endif // No need to lock anything in the feed_record method boost::log::aux::fake_mutex m; @@ -280,6 +277,28 @@ protected: private: struct formatting_context { + class cleanup_guard + { + private: + formatting_context& m_context; + + public: + explicit cleanup_guard(formatting_context& ctx) BOOST_NOEXCEPT : m_context(ctx) + { + } + + ~cleanup_guard() + { + m_context.m_FormattedRecord.clear(); + m_context.m_FormattingStream.rdbuf()->max_size(m_context.m_FormattedRecord.max_size()); + m_context.m_FormattingStream.rdbuf()->storage_overflow(false); + m_context.m_FormattingStream.clear(); + } + + BOOST_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&)) + BOOST_DELETED_FUNCTION(cleanup_guard& operator=(cleanup_guard const&)) + }; + #if !defined(BOOST_LOG_NO_THREADS) //! Object version const unsigned int m_Version; @@ -431,8 +450,7 @@ protected: context = &m_Context; #endif - boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream); - boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord); + typename formatting_context::cleanup_guard cleanup(*context); try { @@ -464,13 +482,10 @@ protected: bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) { #if !defined(BOOST_LOG_NO_THREADS) - unique_lock< BackendMutexT > lock; try { - unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); - if (!tmp_lock.owns_lock()) + if (!backend_mutex.try_lock()) return false; - lock.swap(tmp_lock); } catch (thread_interrupted&) { @@ -484,6 +499,8 @@ protected: this->exception_handler()(); return false; } + + boost::log::aux::exclusive_auto_unlocker< BackendMutexT > unlocker(backend_mutex); #endif // No need to lock anything in the feed_record method boost::log::aux::fake_mutex m; diff --git a/include/boost/log/sources/basic_logger.hpp b/include/boost/log/sources/basic_logger.hpp index 3403928..58bd659 100644 --- a/include/boost/log/sources/basic_logger.hpp +++ b/include/boost/log/sources/basic_logger.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/sources/channel_feature.hpp b/include/boost/log/sources/channel_feature.hpp index aa03490..d7e88c4 100644 --- a/include/boost/log/sources/channel_feature.hpp +++ b/include/boost/log/sources/channel_feature.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/sources/exception_handler_feature.hpp b/include/boost/log/sources/exception_handler_feature.hpp index bd77fca..d290411 100644 --- a/include/boost/log/sources/exception_handler_feature.hpp +++ b/include/boost/log/sources/exception_handler_feature.hpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/boost/log/sources/record_ostream.hpp b/include/boost/log/sources/record_ostream.hpp index b8fcd9f..5fac874 100644 --- a/include/boost/log/sources/record_ostream.hpp +++ b/include/boost/log/sources/record_ostream.hpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/sources/severity_feature.hpp b/include/boost/log/sources/severity_feature.hpp index 6ecf95e..101769b 100644 --- a/include/boost/log/sources/severity_feature.hpp +++ b/include/boost/log/sources/severity_feature.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/support/date_time.hpp b/include/boost/log/support/date_time.hpp index e1c9050..468f02f 100644 --- a/include/boost/log/support/date_time.hpp +++ b/include/boost/log/support/date_time.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/boost/log/utility/strictest_lock.hpp b/include/boost/log/utility/strictest_lock.hpp index 9735961..5dd48b4 100644 --- a/include/boost/log/utility/strictest_lock.hpp +++ b/include/boost/log/utility/strictest_lock.hpp @@ -78,6 +78,11 @@ struct thread_access_mode_of< lock_guard< MutexT > > : mpl::integral_c< lock_acc { }; +template< typename MutexT > +struct thread_access_mode_of< shared_lock_guard< MutexT > > : mpl::integral_c< lock_access_mode, shared_access > +{ +}; + template< typename MutexT > struct thread_access_mode_of< unique_lock< MutexT > > : mpl::integral_c< lock_access_mode, exclusive_access > { diff --git a/src/core.cpp b/src/core.cpp index 1d9dd69..f43d80b 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/format_parser.cpp b/src/format_parser.cpp index d797dd9..1215d6b 100644 --- a/src/format_parser.cpp +++ b/src/format_parser.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/named_scope_format_parser.cpp b/src/named_scope_format_parser.cpp index 16e7bd2..729f1fb 100644 --- a/src/named_scope_format_parser.cpp +++ b/src/named_scope_format_parser.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/posix/object_name.cpp b/src/posix/object_name.cpp index 9465fbb..456e1ea 100644 --- a/src/posix/object_name.cpp +++ b/src/posix/object_name.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/setup/filter_parser.cpp b/src/setup/filter_parser.cpp index efb2402..cf41bca 100644 --- a/src/setup/filter_parser.cpp +++ b/src/setup/filter_parser.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/setup/formatter_parser.cpp b/src/setup/formatter_parser.cpp index e84f157..09ab8ee 100644 --- a/src/setup/formatter_parser.cpp +++ b/src/setup/formatter_parser.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/setup/settings_parser.cpp b/src/setup/settings_parser.cpp index 8af2373..d0ebe6f 100644 --- a/src/setup/settings_parser.cpp +++ b/src/setup/settings_parser.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/windows/object_name.cpp b/src/windows/object_name.cpp index b28848c..e89d100 100644 --- a/src/windows/object_name.cpp +++ b/src/windows/object_name.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/common/make_record.hpp b/test/common/make_record.hpp index bb81589..9d1f028 100644 --- a/test/common/make_record.hpp +++ b/test/common/make_record.hpp @@ -15,7 +15,7 @@ #ifndef BOOST_LOG_TESTS_MAKE_RECORD_HPP_INCLUDED_ #define BOOST_LOG_TESTS_MAKE_RECORD_HPP_INCLUDED_ -#include +#include #include #include diff --git a/test/run/core.cpp b/test/run/core.cpp index f945c03..69b4264 100644 --- a/test/run/core.cpp +++ b/test/run/core.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/run/form_max_size_decor.cpp b/test/run/form_max_size_decor.cpp new file mode 100644 index 0000000..8fec3fa --- /dev/null +++ b/test/run/form_max_size_decor.cpp @@ -0,0 +1,185 @@ +/* + * Copyright Andrey Semashev 2016. + * 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) + */ +/*! + * \file form_max_size_decor.cpp + * \author Andrey Semashev + * \date 09.08.2016 + * + * \brief This header contains tests for the \c max_size_decor formatter. + */ + +#define BOOST_TEST_MODULE form_max_size_decor + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "char_definitions.hpp" +#include "make_record.hpp" + +#define BOOST_UTF8_DECL +#define BOOST_UTF8_BEGIN_NAMESPACE namespace { +#define BOOST_UTF8_END_NAMESPACE } + +#include +#include + +namespace logging = boost::log; +namespace attrs = logging::attributes; +namespace expr = logging::expressions; + +namespace { + +template< typename > +struct test_strings; + +#ifdef BOOST_LOG_USE_CHAR +template< > +struct test_strings< char > : public test_data< char > +{ + static const char* printable_chars() { return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; } + static const char* overflow_marker() { return ">>>"; } +}; +#endif + +#ifdef BOOST_LOG_USE_WCHAR_T +template< > +struct test_strings< wchar_t > : public test_data< wchar_t > +{ + static const wchar_t* printable_chars() { return L" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; } + static const wchar_t* overflow_marker() { return L">>>"; } +}; +#endif + +} // namespace + +BOOST_AUTO_TEST_CASE_TEMPLATE(decorator_formatting, CharT, char_types) +{ + typedef logging::record_view record_view; + typedef logging::attribute_set attr_set; + typedef std::basic_string< CharT > string; + typedef logging::basic_formatting_ostream< CharT > osstream; + typedef logging::basic_formatter< CharT > formatter; + typedef test_strings< CharT > data; + + attrs::constant< string > attr1(data::printable_chars()); + + attr_set set1; + set1[data::attr1()] = attr1; + + record_view rec = make_record_view(set1); + + // Test output truncation + { + string str1, str2; + osstream strm1(str1), strm2(str2); + formatter f = expr::stream << expr::max_size_decor< CharT >(10)[ expr::stream << expr::attr< string >(data::attr1()) << data::some_test_string() << 1234 << data::abc() ]; + f(rec, strm1); + strm2 << string(data::printable_chars(), 10); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + + // Test output truncation with a marker + { + string str1, str2; + osstream strm1(str1), strm2(str2); + formatter f = expr::stream << expr::max_size_decor(10, data::overflow_marker())[ expr::stream << expr::attr< string >(data::attr1()) << data::some_test_string() << 1234 << data::abc() ]; + f(rec, strm1); + strm2 << string(data::printable_chars(), 7) << data::overflow_marker(); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + + // Test nested decorators, when the outer decorator enforces the limit that includes the inner decorator + { + string str1, str2; + osstream strm1(str1), strm2(str2); + formatter f = expr::stream << expr::max_size_decor(35, data::overflow_marker())[ + expr::stream << data::abcdefg0123456789() << expr::max_size_decor(10, data::overflow_marker())[ expr::stream << expr::attr< string >(data::attr1()) ] << data::abcdefg0123456789() + ]; + f(rec, strm1); + strm2 << data::abcdefg0123456789() << string(data::printable_chars(), 7) << data::overflow_marker() << string(data::abcdefg0123456789(), 5) << data::overflow_marker(); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + + // Test nested decorators, when the outer decorator enforces the limit that also limits the inner decorator + { + string str1, str2; + osstream strm1(str1), strm2(str2); + formatter f = expr::stream << expr::max_size_decor(25, data::overflow_marker())[ + expr::stream << data::abcdefg0123456789() << expr::max_size_decor(10, data::overflow_marker())[ expr::stream << expr::attr< string >(data::attr1()) ] << data::abcdefg0123456789() + ]; + f(rec, strm1); + strm2 << data::abcdefg0123456789() << string(data::printable_chars(), 5) << data::overflow_marker(); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } +} + +namespace { + +const char narrow_chars[] = +{ + static_cast< char >(0xd0), static_cast< char >(0x9f), static_cast< char >(0xd1), static_cast< char >(0x80), + static_cast< char >(0xd0), static_cast< char >(0xb8), static_cast< char >(0xd0), static_cast< char >(0xb2), + static_cast< char >(0xd0), static_cast< char >(0xb5), static_cast< char >(0xd1), static_cast< char >(0x82), + ',', ' ', + static_cast< char >(0xd0), static_cast< char >(0xbc), static_cast< char >(0xd0), static_cast< char >(0xb8), + static_cast< char >(0xd1), static_cast< char >(0x80), '!', 0 +}; + +} // namespace + +BOOST_AUTO_TEST_CASE(character_boundary_maintenance) +{ + typedef logging::record_view record_view; + typedef logging::attribute_set attr_set; + typedef std::basic_string< char > string; + typedef logging::basic_formatting_ostream< char > osstream; + typedef logging::basic_formatter< char > formatter; + typedef test_strings< char > data; + + std::locale loc(std::locale::classic(), new utf8_codecvt_facet()); + + attrs::constant< string > attr1(narrow_chars); + + attr_set set1; + set1[data::attr1()] = attr1; + + record_view rec = make_record_view(set1); + + // Test that output truncation does not happen in the middle of a multibyte character + { + string str1, str2; + osstream strm1(str1), strm2(str2); + strm1.imbue(loc); + strm2.imbue(loc); + formatter f = expr::stream << expr::max_size_decor< char >(7)[ expr::stream << expr::attr< string >(data::attr1()) ]; + f(rec, strm1); + strm2 << string(narrow_chars, 6); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } + + // Test output truncation with a marker, when the marker length would have caused truncation in the middle of a multibyte character + { + string str1, str2; + osstream strm1(str1), strm2(str2); + strm1.imbue(loc); + strm2.imbue(loc); + formatter f = expr::stream << expr::max_size_decor(6, data::overflow_marker())[ expr::stream << expr::attr< string >(data::attr1()) ]; + f(rec, strm1); + strm2 << string(narrow_chars, 2) << data::overflow_marker(); + BOOST_CHECK(equal_strings(strm1.str(), strm2.str())); + } +} diff --git a/test/run/util_ipc_object_name.cpp b/test/run/util_ipc_object_name.cpp index 8373257..42ad03c 100644 --- a/test/run/util_ipc_object_name.cpp +++ b/test/run/util_ipc_object_name.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include "char_definitions.hpp" const char test_object_name1[] = "boost_log_test_object_name1"; diff --git a/test/run/util_ipc_reliable_mq.cpp b/test/run/util_ipc_reliable_mq.cpp index ec535d0..d4b68ff 100644 --- a/test/run/util_ipc_reliable_mq.cpp +++ b/test/run/util_ipc_reliable_mq.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #if !defined(BOOST_LOG_NO_THREADS) #include #include