diff --git a/include/boost/log/expressions/formatter.hpp b/include/boost/log/expressions/formatter.hpp index 4e19db3..6d70363 100644 --- a/include/boost/log/expressions/formatter.hpp +++ b/include/boost/log/expressions/formatter.hpp @@ -70,6 +70,25 @@ public: } }; +//! Default log record message formatter +struct message_formatter +{ + typedef void result_type; + + message_formatter() : m_MessageName(expressions::tag::message::get_name()) + { + } + + template< typename StreamT > + result_type operator() (record_view const& rec, StreamT& strm) const + { + boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm)); + } + +private: + const attribute_name m_MessageName; +}; + } // namespace aux } // namespace expressions @@ -96,24 +115,6 @@ private: //! Filter function type typedef boost::log::aux::light_function< void (record_view const&, expressions::aux::stream_ref< stream_type >) > formatter_type; - //! Default formatter, always returns \c true - struct default_formatter - { - typedef void result_type; - - default_formatter() : m_MessageName(expressions::tag::message::get_name()) - { - } - - result_type operator() (record_view const& rec, stream_type& strm) const - { - boost::log::visit< expressions::tag::message::value_type >(m_MessageName, rec, boost::log::bind_output(strm)); - } - - private: - const attribute_name m_MessageName; - }; - private: //! Formatter function formatter_type m_Formatter; @@ -122,7 +123,7 @@ public: /*! * Default constructor. Creates a formatter that only outputs log message. */ - basic_formatter() : m_Formatter(default_formatter()) + basic_formatter() : m_Formatter(expressions::aux::message_formatter()) { } /*! diff --git a/src/dump_avx2.cpp b/src/dump_avx2.cpp index f27a930..28eb5c2 100644 --- a/src/dump_avx2.cpp +++ b/src/dump_avx2.cpp @@ -22,6 +22,12 @@ #include #include +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || \ + defined(_M_X64) +#define BOOST_LOG_AUX_X86_64 +#endif + namespace boost { BOOST_LOG_OPEN_NAMESPACE @@ -46,6 +52,8 @@ union ymm_constant { uint8_t as_bytes[32]; __m256i as_mm; + + BOOST_FORCEINLINE operator __m256i () const { return as_mm; } }; static const ymm_constant mm_shuffle_pattern1 = {{ 0x80, 0, 1, 0x80, 2, 3, 0x80, 4, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 0x80, 0, 1, 0x80, 2, 3, 0x80, 4, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80 }}; @@ -53,6 +61,30 @@ static const ymm_constant mm_shuffle_pattern2 = {{ 0, 1, 0x80, 2, 3, 0x80, 4, 5, static const ymm_constant mm_shuffle_pattern3 = {{ 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 10, 11, 0x80, 12, 13, 0x80, 14, 15, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 10, 11, 0x80, 12, 13, 0x80, 14, 15 }}; static const ymm_constant mm_shuffle_pattern13 = {{ 0x80, 0, 1, 0x80, 2, 3, 0x80, 4, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 10, 11, 0x80, 12, 13, 0x80, 14, 15 }}; +#if defined(BOOST_LOG_AUX_X86_64) + +// x86-64 architecture has more registers which we can utilize to pass constants +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL __m128i mm_15, __m128i mm_9, __m128i mm_char_0, __m128i mm_char_space, +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_15, mm_9, mm_char_0, mm_char_space, +#define BOOST_LOG_AUX_MM_CONSTANTS \ + const __m256i mm_15 = _mm256_set1_epi32(0x0F0F0F0F);\ + const __m256i mm_9 = _mm256_set1_epi32(0x09090909);\ + const __m256i mm_char_0 = _mm256_set1_epi32(0x30303030);\ + const __m256i mm_char_space = _mm256_set1_epi32(0x20202020); + +#else + +// MSVC in 32-bit mode is not able to pass all constants to dump_pack, and is also not able to align them on the stack, so we have to fetch them from global constants +static const ymm_constant mm_15 = {{ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }}; +static const ymm_constant mm_9 = {{ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09 }}; +static const ymm_constant mm_char_0 = {{ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 }}; +static const ymm_constant mm_char_space = {{ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }}; +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS +#define BOOST_LOG_AUX_MM_CONSTANTS + +#endif + /*! * \brief Dumps a pack of input data into a string of 8 bit ASCII characters. * @@ -60,8 +92,8 @@ static const ymm_constant mm_shuffle_pattern13 = {{ 0x80, 0, 1, 0x80, 2, 3, 0x80 */ static BOOST_FORCEINLINE void dump_pack ( - __m256i mm_15, __m256i mm_9, __m256i mm_char_0, __m256i mm_char_10_to_a, __m256i mm_char_space, - __m256i mm_input, + BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL + __m256i mm_char_10_to_a, __m256i mm_input, __m256i& mm_output1, __m256i& mm_output2, __m256i& mm_output3 ) { @@ -100,8 +132,8 @@ static BOOST_FORCEINLINE void dump_pack //! Dumps a pack of input data into a string of 8 bit ASCII characters static BOOST_FORCEINLINE void dump_pack ( - __m256i mm_15, __m256i mm_9, __m256i mm_char_0, __m256i mm_char_10_to_a, __m256i mm_char_space, - __m128i mm_input, + BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL + __m256i mm_char_10_to_a, __m128i mm_input, __m128i& mm_output1, __m128i& mm_output2, __m128i& mm_output3 ) { @@ -185,13 +217,10 @@ BOOST_FORCEINLINE void dump_data_avx2(const void* data, std::size_t size, std::b if (prealign_size) { __m256i mm_input = _mm256_lddqu_si256(reinterpret_cast< const __m256i* >(p)); - const __m256i mm_15 = _mm256_set1_epi32(0x0F0F0F0F); - const __m256i mm_9 = _mm256_set1_epi32(0x09090909); - const __m256i mm_char_0 = _mm256_set1_epi32(0x30303030); - const __m256i mm_char_space = _mm256_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS __m256i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters_x3(mm_output1, mm_output2, mm_output3, buf); @@ -207,16 +236,13 @@ BOOST_FORCEINLINE void dump_data_avx2(const void* data, std::size_t size, std::b for (std::size_t i = 0; i < stride_count; ++i) { char_type* b = buf; - const __m256i mm_15 = _mm256_set1_epi32(0x0F0F0F0F); - const __m256i mm_9 = _mm256_set1_epi32(0x09090909); - const __m256i mm_char_0 = _mm256_set1_epi32(0x30303030); - const __m256i mm_char_space = _mm256_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS for (unsigned int j = 0; j < packs_per_stride; ++j, b += 3u * 32u, p += 32u) { __m256i mm_input = _mm256_load_si256(reinterpret_cast< const __m256i* >(p)); __m256i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters_x3(mm_output1, mm_output2, mm_output3, b); } @@ -232,13 +258,10 @@ BOOST_FORCEINLINE void dump_data_avx2(const void* data, std::size_t size, std::b while (tail_size >= 16u) { __m128i mm_input = _mm_load_si128(reinterpret_cast< const __m128i* >(p)); - const __m256i mm_15 = _mm256_set1_epi32(0x0F0F0F0F); - const __m256i mm_9 = _mm256_set1_epi32(0x09090909); - const __m256i mm_char_0 = _mm256_set1_epi32(0x30303030); - const __m256i mm_char_space = _mm256_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS __m128i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters(mm_output1, b); store_characters(mm_output2, b + 16u); diff --git a/src/dump_ssse3.cpp b/src/dump_ssse3.cpp index 5b0a99a..81fa15a 100644 --- a/src/dump_ssse3.cpp +++ b/src/dump_ssse3.cpp @@ -22,6 +22,12 @@ #include #include +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || \ + defined(_M_X64) +#define BOOST_LOG_AUX_X86_64 +#endif + namespace boost { BOOST_LOG_OPEN_NAMESPACE @@ -46,17 +52,43 @@ union xmm_constant { uint8_t as_bytes[16]; __m128i as_mm; + + BOOST_FORCEINLINE operator __m128i () const { return as_mm; } }; static const xmm_constant mm_shuffle_pattern1 = {{ 0x80, 0, 1, 0x80, 2, 3, 0x80, 4, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80 }}; static const xmm_constant mm_shuffle_pattern2 = {{ 0, 1, 0x80, 2, 3, 0x80, 4, 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 10 }}; static const xmm_constant mm_shuffle_pattern3 = {{ 5, 0x80, 6, 7, 0x80, 8, 9, 0x80, 10, 11, 0x80, 12, 13, 0x80, 14, 15 }}; +#if defined(BOOST_LOG_AUX_X86_64) + +// x86-64 architecture has more registers which we can utilize to pass constants +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL __m128i mm_15, __m128i mm_9, __m128i mm_char_0, __m128i mm_char_space, +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_15, mm_9, mm_char_0, mm_char_space, +#define BOOST_LOG_AUX_MM_CONSTANTS \ + const __m128i mm_15 = _mm_set1_epi32(0x0F0F0F0F);\ + const __m128i mm_9 = _mm_set1_epi32(0x09090909);\ + const __m128i mm_char_0 = _mm_set1_epi32(0x30303030);\ + const __m128i mm_char_space = _mm_set1_epi32(0x20202020); + +#else + +// MSVC in 32-bit mode is not able to pass all constants to dump_pack, and is also not able to align them on the stack, so we have to fetch them from global constants +static const xmm_constant mm_15 = {{ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }}; +static const xmm_constant mm_9 = {{ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09 }}; +static const xmm_constant mm_char_0 = {{ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 }}; +static const xmm_constant mm_char_space = {{ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }}; +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL +#define BOOST_LOG_AUX_MM_CONSTANT_ARGS +#define BOOST_LOG_AUX_MM_CONSTANTS + +#endif + //! Dumps a pack of input data into a string of 8 bit ASCII characters static BOOST_FORCEINLINE void dump_pack ( - __m128i mm_15, __m128i mm_9, __m128i mm_char_0, __m128i mm_char_10_to_a, __m128i mm_char_space, - __m128i mm_input, + BOOST_LOG_AUX_MM_CONSTANT_ARGS_DECL + __m128i mm_char_10_to_a, __m128i mm_input, __m128i& mm_output1, __m128i& mm_output2, __m128i& mm_output3 ) { @@ -146,13 +178,10 @@ BOOST_FORCEINLINE void dump_data_ssse3(const void* data, std::size_t size, std:: if (BOOST_UNLIKELY(prealign_size > 0)) { __m128i mm_input = _mm_lddqu_si128(reinterpret_cast< const __m128i* >(p)); - const __m128i mm_15 = _mm_set1_epi32(0x0F0F0F0F); - const __m128i mm_9 = _mm_set1_epi32(0x09090909); - const __m128i mm_char_0 = _mm_set1_epi32(0x30303030); - const __m128i mm_char_space = _mm_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS __m128i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters(mm_output1, buf); store_characters(mm_output2, buf + 16u); @@ -169,16 +198,13 @@ BOOST_FORCEINLINE void dump_data_ssse3(const void* data, std::size_t size, std:: for (std::size_t i = 0; i < stride_count; ++i) { char_type* b = buf; - const __m128i mm_15 = _mm_set1_epi32(0x0F0F0F0F); - const __m128i mm_9 = _mm_set1_epi32(0x09090909); - const __m128i mm_char_0 = _mm_set1_epi32(0x30303030); - const __m128i mm_char_space = _mm_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS for (unsigned int j = 0; j < packs_per_stride; ++j, b += 3u * 16u, p += 16u) { __m128i mm_input = _mm_load_si128(reinterpret_cast< const __m128i* >(p)); __m128i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters(mm_output1, b); store_characters(mm_output2, b + 16u); @@ -195,13 +221,10 @@ BOOST_FORCEINLINE void dump_data_ssse3(const void* data, std::size_t size, std:: while (tail_size >= 16u) { __m128i mm_input = _mm_load_si128(reinterpret_cast< const __m128i* >(p)); - const __m128i mm_15 = _mm_set1_epi32(0x0F0F0F0F); - const __m128i mm_9 = _mm_set1_epi32(0x09090909); - const __m128i mm_char_0 = _mm_set1_epi32(0x30303030); - const __m128i mm_char_space = _mm_set1_epi32(0x20202020); + BOOST_LOG_AUX_MM_CONSTANTS __m128i mm_output1, mm_output2, mm_output3; - dump_pack(mm_15, mm_9, mm_char_0, mm_char_10_to_a, mm_char_space, mm_input, mm_output1, mm_output2, mm_output3); + dump_pack(BOOST_LOG_AUX_MM_CONSTANT_ARGS mm_char_10_to_a, mm_input, mm_output1, mm_output2, mm_output3); store_characters(mm_output1, b); store_characters(mm_output2, b + 16u); diff --git a/src/formatter_parser.cpp b/src/formatter_parser.cpp index 976efa1..94a1b49 100644 --- a/src/formatter_parser.cpp +++ b/src/formatter_parser.cpp @@ -25,15 +25,13 @@ #include #include #include -#include -#include -#include -#include +#include #include #include #include #include #include +#include #include #include #if !defined(BOOST_LOG_NO_THREADS) @@ -148,6 +146,28 @@ private: SecondT m_second; }; +//! String literal formatter +template< typename CharT > +struct literal_formatter +{ + typedef void result_type; + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef basic_formatting_ostream< char_type > stream_type; + + explicit literal_formatter(BOOST_RV_REF(string_type) str) : m_str(boost::move(str)) + { + } + + result_type operator() (record_view const& rec, stream_type& strm) const + { + strm << m_str; + } + +private: + const string_type m_str; +}; + //! Formatter parsing grammar template< typename CharT > class formatter_parser @@ -367,7 +387,7 @@ private: if (m_AttrName == log::aux::default_attribute_names::message()) { // We make a special treatment for the message text formatter - append_formatter(expressions::stream << expressions::message); + append_formatter(expressions::aux::message_formatter()); } else { @@ -387,7 +407,7 @@ private: { string_type s(begin, end); constants::translate_escape_sequences(s); - append_formatter(expressions::stream << s); + append_formatter(literal_formatter< char_type >(boost::move(s))); } //! The method appends a formatter part to the final formatter diff --git a/src/text_file_backend.cpp b/src/text_file_backend.cpp index f8496c2..3cc09cb 100644 --- a/src/text_file_backend.cpp +++ b/src/text_file_backend.cpp @@ -48,12 +48,9 @@ #include #include #include -#include #include #include #include -#include -#include #include #include #include @@ -135,7 +132,11 @@ BOOST_LOG_ANONYMOUS_NAMESPACE { static const char_type dot = '.'; static const char_type newline = '\n'; - static bool is_digit(char c) { return (isdigit(c) != 0); } + static bool is_digit(char c) + { + using namespace std; + return (isdigit(c) != 0); + } static std::string default_file_name_pattern() { return "%5N.log"; } }; @@ -180,7 +181,11 @@ BOOST_LOG_ANONYMOUS_NAMESPACE { static const char_type dot = L'.'; static const char_type newline = L'\n'; - static bool is_digit(wchar_t c) { return (iswdigit(c) != 0); } + static bool is_digit(wchar_t c) + { + using namespace std; + return (iswdigit(c) != 0); + } static std::wstring default_file_name_pattern() { return L"%5N.log"; } }; @@ -325,21 +330,47 @@ BOOST_LOG_ANONYMOUS_NAMESPACE { bool parse_counter_placeholder(path_string_type::const_iterator& it, path_string_type::const_iterator end, unsigned int& width) { typedef file_char_traits< path_char_type > traits_t; - return qi::parse - ( - it, end, - ( - -( - qi::lit(traits_t::zero) | - qi::lit(traits_t::plus) | - qi::lit(traits_t::minus) | - qi::lit(traits_t::space) - ) >> - -(qi::uint_[boost::log::as_action(boost::log::bind_assign(width))]) >> - -(qi::lit(traits_t::dot) >> qi::uint_) >> - qi::lit(traits_t::number_placeholder) - ) - ); + if (it == end) + return false; + + path_char_type c = *it; + if (c == traits_t::zero || c == traits_t::space || c == traits_t::plus || c == traits_t::minus) + { + // Skip filler and alignment specification + ++it; + if (it == end) + return false; + c = *it; + } + + if (traits_t::is_digit(c)) + { + // Parse width + if (!qi::parse(it, end, qi::uint_, width)) + return false; + if (it == end) + return false; + c = *it; + } + + if (c == traits_t::dot) + { + // Skip precision + ++it; + while (it != end && traits_t::is_digit(*it)) + ++it; + if (it == end) + return false; + c = *it; + } + + if (c == traits_t::number_placeholder) + { + ++it; + return true; + } + + return false; } //! The function matches the file name and the pattern @@ -1222,15 +1253,19 @@ BOOST_LOG_API void text_file_backend::set_file_name_pattern_internal(filesystem: ++placeholder_count; - if (!counter_found && parse_counter_placeholder(it, end, width)) + if (!counter_found) { - // We've found the file counter placeholder in the pattern - counter_found = true; - counter_pos = placeholder_begin - name_pattern.begin(); - name_pattern.erase(counter_pos, it - placeholder_begin); - --placeholder_count; - it = name_pattern.begin() + counter_pos; - end = name_pattern.end(); + path_string_type::const_iterator it2 = it; + if (parse_counter_placeholder(it2, end, width)) + { + // We've found the file counter placeholder in the pattern + counter_found = true; + counter_pos = placeholder_begin - name_pattern.begin(); + name_pattern.erase(counter_pos, it2 - placeholder_begin); + --placeholder_count; + it = name_pattern.begin() + counter_pos; + end = name_pattern.end(); + } } } while (it != end);