Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84512 - in trunk: boost/log/utility libs/log/test/run
From: andrey.semashev_at_[hidden]
Date: 2013-05-26 11:38:20


Author: andysem
Date: 2013-05-26 11:38:19 EDT (Sun, 26 May 2013)
New Revision: 84512
URL: http://svn.boost.org/trac/boost/changeset/84512

Log:
Refs. #8614. Width specification now works correctly for strings.
Added:
   trunk/libs/log/test/run/util_formatting_ostream.cpp (contents, props changed)
Text files modified:
   trunk/boost/log/utility/formatting_ostream.hpp | 114 +++++++++++++++++++++++----------------
   1 files changed, 68 insertions(+), 46 deletions(-)

Modified: trunk/boost/log/utility/formatting_ostream.hpp
==============================================================================
--- trunk/boost/log/utility/formatting_ostream.hpp (original)
+++ trunk/boost/log/utility/formatting_ostream.hpp 2013-05-26 11:38:19 EDT (Sun, 26 May 2013)
@@ -19,6 +19,7 @@
 #include <string>
 #include <memory>
 #include <locale>
+#include <boost/utility/string_ref_fwd.hpp>
 #include <boost/type_traits/remove_cv.hpp>
 #include <boost/log/detail/config.hpp>
 #include <boost/log/detail/attachable_sstream_buf.hpp>
@@ -34,14 +35,6 @@
 
 namespace boost {
 
-#ifndef BOOST_LOG_DOXYGEN_PASS
-
-// This forward is needed for operator<<
-template< typename CharT, typename TraitsT >
-class basic_string_ref;
-
-#endif
-
 BOOST_LOG_OPEN_NAMESPACE
 
 namespace aux {
@@ -127,6 +120,9 @@
         explicit sentry(basic_formatting_ostream& strm) : base_type(strm.stream())
         {
         }
+
+ BOOST_LOG_DELETED_FUNCTION(sentry(sentry const&))
+ BOOST_LOG_DELETED_FUNCTION(sentry& operator= (sentry const&))
     };
 
 private:
@@ -359,7 +355,7 @@
     typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
     write(const OtherCharT* p, std::streamsize size)
     {
- flush();
+ m_stream.flush();
 
         string_type* storage = m_streambuf.storage();
         BOOST_ASSERT(storage != NULL);
@@ -386,49 +382,41 @@
 
     basic_formatting_ostream& operator<< (char c)
     {
- this->put(c);
- return *this;
+ return this->formatted_write(&c, 1);
     }
     basic_formatting_ostream& operator<< (const char* p)
     {
- this->write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
- return *this;
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char >::length(p)));
     }
 
 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
     basic_formatting_ostream& operator<< (wchar_t c)
     {
- this->put(c);
- return *this;
+ return this->formatted_write(&c, 1);
     }
     basic_formatting_ostream& operator<< (const wchar_t* p)
     {
- this->write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
- return *this;
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< wchar_t >::length(p)));
     }
 #endif
 #if !defined(BOOST_NO_CXX11_CHAR16_T)
     basic_formatting_ostream& operator<< (char16_t c)
     {
- this->put(c);
- return *this;
+ return this->formatted_write(&c, 1);
     }
     basic_formatting_ostream& operator<< (const char16_t* p)
     {
- this->write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
- return *this;
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char16_t >::length(p)));
     }
 #endif
 #if !defined(BOOST_NO_CXX11_CHAR32_T)
     basic_formatting_ostream& operator<< (char32_t c)
     {
- this->put(c);
- return *this;
+ return this->formatted_write(&c, 1);
     }
     basic_formatting_ostream& operator<< (const char32_t* p)
     {
- this->write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
- return *this;
+ return this->formatted_write(p, static_cast< std::streamsize >(std::char_traits< char32_t >::length(p)));
     }
 #endif
 
@@ -518,6 +506,27 @@
         return *this;
     }
 
+ template< typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
+ {
+ return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.c_str(), static_cast< std::streamsize >(str.size()));
+ }
+
+ template< typename OtherCharT, typename OtherTraitsT >
+ friend typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream& >::type
+ operator<< (basic_formatting_ostream& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
+ {
+ return strm.formatted_write(str.data(), static_cast< std::streamsize >(str.size()));
+ }
+
 private:
     void init_stream()
     {
@@ -533,6 +542,40 @@
         m_stream.fill(static_cast< char_type >(' '));
     }
 
+ template< typename OtherCharT >
+ basic_formatting_ostream& formatted_write(const OtherCharT* p, std::streamsize size)
+ {
+ sentry guard(*this);
+ if (guard)
+ {
+ m_stream.flush();
+ string_type* const storage = m_streambuf.storage();
+
+ const std::streamsize w = m_stream.width();
+ if (w <= size)
+ {
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+ }
+ else
+ {
+ const bool align_left = (m_stream.flags() & ostream_type::adjustfield) == ostream_type::left;
+ typename string_type::size_type const alignment_size =
+ static_cast< typename string_type::size_type >(w - size);
+ if (!align_left)
+ storage->append(alignment_size, m_stream.fill());
+
+ aux::code_convert(p, static_cast< std::size_t >(size), *storage, m_stream.getloc());
+
+ if (align_left)
+ storage->append(alignment_size, m_stream.fill());
+ }
+
+ m_stream.width(0);
+ }
+
+ return *this;
+ }
+
     //! Copy constructor (closed)
     BOOST_LOG_DELETED_FUNCTION(basic_formatting_ostream(basic_formatting_ostream const& that))
     //! Assignment (closed)
@@ -619,27 +662,6 @@
     return strm;
 }
 
-template< typename CharT, typename TraitsT, typename AllocatorT, typename OtherCharT, typename OtherTraitsT, typename OtherAllocatorT >
-inline typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >::type
-operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, std::basic_string< OtherCharT, OtherTraitsT, OtherAllocatorT > const& str)
-{
- return strm.write(str.c_str(), static_cast< std::streamsize >(str.size()));
-}
-
-template< typename CharT, typename TraitsT, typename AllocatorT, typename OtherCharT, typename OtherTraitsT >
-inline typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >::type
-operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, basic_string_literal< OtherCharT, OtherTraitsT > const& str)
-{
- return strm.write(str.c_str(), static_cast< std::streamsize >(str.size()));
-}
-
-template< typename CharT, typename TraitsT, typename AllocatorT, typename OtherCharT, typename OtherTraitsT >
-inline typename aux::enable_if_char_type< OtherCharT, basic_formatting_ostream< CharT, TraitsT, AllocatorT >& >::type
-operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, basic_string_ref< OtherCharT, OtherTraitsT > const& str)
-{
- return strm.write(str.data(), static_cast< std::streamsize >(str.size()));
-}
-
 BOOST_LOG_CLOSE_NAMESPACE // namespace log
 
 } // namespace boost

Added: trunk/libs/log/test/run/util_formatting_ostream.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/log/test/run/util_formatting_ostream.cpp 2013-05-26 11:38:19 EDT (Sun, 26 May 2013)
@@ -0,0 +1,211 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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 util_formatting_ostream.cpp
+ * \author Andrey Semashev
+ * \date 26.05.2013
+ *
+ * \brief This header contains tests for the formatting output stream wrapper.
+ */
+
+#define BOOST_TEST_MODULE util_formatting_ostream
+
+#include <locale>
+#include <string>
+#include <iomanip>
+#include <sstream>
+#include <algorithm>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility/string_ref.hpp>
+#include <boost/log/utility/formatting_ostream.hpp>
+#include "char_definitions.hpp"
+
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+#define BOOST_UTF8_DECL
+#define BOOST_UTF8_BEGIN_NAMESPACE namespace {
+#define BOOST_UTF8_END_NAMESPACE }
+
+#include <boost/detail/utf8_codecvt_facet.hpp>
+#include <boost/detail/utf8_codecvt_facet.ipp>
+
+#endif // defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+namespace logging = boost::log;
+
+namespace {
+
+template< typename CharT >
+struct test_impl
+{
+ typedef CharT char_type;
+ typedef test_data< char_type > strings;
+ typedef std::basic_string< char_type > string_type;
+ typedef std::basic_ostringstream< char_type > ostream_type;
+ typedef logging::basic_formatting_ostream< char_type > formatting_ostream_type;
+
+ template< typename StringT >
+ static void width_formatting()
+ {
+ // Check that widening works
+ {
+ string_type str_fmt;
+ formatting_ostream_type strm_fmt(str_fmt);
+ strm_fmt << strings::abc() << std::setw(8) << (StringT)strings::abcd() << strings::ABC();
+ strm_fmt.flush();
+
+ ostream_type strm_correct;
+ strm_correct << strings::abc() << std::setw(8) << (StringT)strings::abcd() << strings::ABC();
+
+ BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str()));
+ }
+
+ // Check that the string is not truncated
+ {
+ string_type str_fmt;
+ formatting_ostream_type strm_fmt(str_fmt);
+ strm_fmt << strings::abc() << std::setw(1) << (StringT)strings::abcd() << strings::ABC();
+ strm_fmt.flush();
+
+ ostream_type strm_correct;
+ strm_correct << strings::abc() << std::setw(1) << (StringT)strings::abcd() << strings::ABC();
+
+ BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str()));
+ }
+ }
+
+ template< typename StringT >
+ static void fill_formatting()
+ {
+ string_type str_fmt;
+ formatting_ostream_type strm_fmt(str_fmt);
+ strm_fmt << strings::abc() << std::setfill(static_cast< char_type >('x')) << std::setw(8) << (StringT)strings::abcd() << strings::ABC();
+ strm_fmt.flush();
+
+ ostream_type strm_correct;
+ strm_correct << strings::abc() << std::setfill(static_cast< char_type >('x')) << std::setw(8) << (StringT)strings::abcd() << strings::ABC();
+
+ BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str()));
+ }
+
+ template< typename StringT >
+ static void alignment()
+ {
+ // Left alignment
+ {
+ string_type str_fmt;
+ formatting_ostream_type strm_fmt(str_fmt);
+ strm_fmt << strings::abc() << std::setw(8) << std::left << (StringT)strings::abcd() << strings::ABC();
+ strm_fmt.flush();
+
+ ostream_type strm_correct;
+ strm_correct << strings::abc() << std::setw(8) << std::left << (StringT)strings::abcd() << strings::ABC();
+
+ BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str()));
+ }
+
+ // Right alignment
+ {
+ string_type str_fmt;
+ formatting_ostream_type strm_fmt(str_fmt);
+ strm_fmt << strings::abc() << std::setw(8) << std::right << (StringT)strings::abcd() << strings::ABC();
+ strm_fmt.flush();
+
+ ostream_type strm_correct;
+ strm_correct << strings::abc() << std::setw(8) << std::right << (StringT)strings::abcd() << strings::ABC();
+
+ BOOST_CHECK(equal_strings(strm_fmt.str(), strm_correct.str()));
+ }
+ }
+};
+
+} // namespace
+
+// Test support for width formatting
+BOOST_AUTO_TEST_CASE_TEMPLATE(width_formatting, CharT, char_types)
+{
+ typedef test_impl< CharT > test;
+ test::BOOST_NESTED_TEMPLATE width_formatting< const CharT* >();
+ test::BOOST_NESTED_TEMPLATE width_formatting< typename test::string_type >();
+ test::BOOST_NESTED_TEMPLATE width_formatting< boost::basic_string_ref< CharT > >();
+}
+
+// Test support for filler character setup
+BOOST_AUTO_TEST_CASE_TEMPLATE(fill_formatting, CharT, char_types)
+{
+ typedef test_impl< CharT > test;
+ test::BOOST_NESTED_TEMPLATE fill_formatting< const CharT* >();
+ test::BOOST_NESTED_TEMPLATE fill_formatting< typename test::string_type >();
+ test::BOOST_NESTED_TEMPLATE fill_formatting< boost::basic_string_ref< CharT > >();
+}
+
+// Test support for text alignment
+BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
+{
+ typedef test_impl< CharT > test;
+ test::BOOST_NESTED_TEMPLATE alignment< const CharT* >();
+ test::BOOST_NESTED_TEMPLATE alignment< typename test::string_type >();
+ test::BOOST_NESTED_TEMPLATE alignment< boost::basic_string_ref< CharT > >();
+}
+
+#if defined(BOOST_LOG_USE_CHAR) && defined(BOOST_LOG_USE_WCHAR_T)
+
+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
+};
+const wchar_t wide_chars[] = { 0x041f, 0x0440, 0x0438, 0x0432, 0x0435, 0x0442, L',', L' ', 0x043c, 0x0438, 0x0440, L'!', 0 };
+
+template< typename StringT >
+void test_narrowing_code_conversion()
+{
+ std::locale loc(std::locale::classic(), new utf8_codecvt_facet());
+
+ std::string str_fmt;
+ logging::formatting_ostream strm_fmt(str_fmt);
+ strm_fmt.imbue(loc);
+ strm_fmt << (StringT)wide_chars;
+ strm_fmt.flush();
+
+ BOOST_CHECK(equal_strings(str_fmt, std::string(narrow_chars)));
+}
+
+template< typename StringT >
+void test_widening_code_conversion()
+{
+ std::locale loc(std::locale::classic(), new utf8_codecvt_facet());
+
+ std::wstring str_fmt;
+ logging::wformatting_ostream strm_fmt(str_fmt);
+ strm_fmt.imbue(loc);
+ strm_fmt << (StringT)narrow_chars;
+ strm_fmt.flush();
+
+ BOOST_CHECK(equal_strings(str_fmt, std::wstring(wide_chars)));
+}
+
+} // namespace
+
+// Test character code conversion
+BOOST_AUTO_TEST_CASE(character_code_conversion)
+{
+ test_narrowing_code_conversion< const wchar_t* >();
+ test_widening_code_conversion< const char* >();
+ test_narrowing_code_conversion< std::wstring >();
+ test_widening_code_conversion< std::string >();
+ test_narrowing_code_conversion< boost::wstring_ref >();
+ test_widening_code_conversion< boost::string_ref >();
+}
+
+#endif


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk