Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:21

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   format.hpp
0009  * \author Andrey Semashev
0010  * \date   15.11.2012
0011  *
0012  * \brief  This header is the Boost.Log library implementation, see the library documentation
0013  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
0014  */
0015 
0016 #ifndef BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
0017 #define BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_
0018 
0019 #include <cstddef>
0020 #include <string>
0021 #include <vector>
0022 #include <iosfwd>
0023 #include <boost/assert.hpp>
0024 #include <boost/move/core.hpp>
0025 #include <boost/move/utility_core.hpp>
0026 #include <boost/core/uncaught_exceptions.hpp>
0027 #include <boost/log/detail/config.hpp>
0028 #include <boost/log/detail/cleanup_scope_guard.hpp>
0029 #include <boost/log/utility/formatting_ostream.hpp>
0030 #include <boost/log/detail/header.hpp>
0031 
0032 #ifdef BOOST_HAS_PRAGMA_ONCE
0033 #pragma once
0034 #endif
0035 
0036 namespace boost {
0037 
0038 BOOST_LOG_OPEN_NAMESPACE
0039 
0040 namespace aux {
0041 
0042 //! An element (either literal or placeholder) of the format string
0043 struct format_element
0044 {
0045     //! Argument placeholder number or -1 if it's not a placeholder (i.e. a literal)
0046     int arg_number;
0047     //! If the element describes a constant literal, the starting character and length of the literal
0048     unsigned int literal_start_pos, literal_len;
0049 
0050     format_element() : arg_number(0), literal_start_pos(0), literal_len(0)
0051     {
0052     }
0053 
0054     static format_element literal(unsigned int start_pos, unsigned int len)
0055     {
0056         format_element el;
0057         el.arg_number = -1;
0058         el.literal_start_pos = start_pos;
0059         el.literal_len = len;
0060         return el;
0061     }
0062 
0063     static format_element positional_argument(unsigned int arg_n)
0064     {
0065         format_element el;
0066         el.arg_number = arg_n;
0067         return el;
0068     }
0069 };
0070 
0071 //! Parsed format string description
0072 template< typename CharT >
0073 struct format_description
0074 {
0075     BOOST_COPYABLE_AND_MOVABLE_ALT(format_description)
0076 
0077 public:
0078     //! Character type
0079     typedef CharT char_type;
0080     //! String type
0081     typedef std::basic_string< char_type > string_type;
0082 
0083     //! Array of format element descriptors
0084     typedef std::vector< format_element > format_element_list;
0085 
0086     //! Characters of all literal parts of the format string
0087     string_type literal_chars;
0088     //! Format element descriptors
0089     format_element_list format_elements;
0090 
0091     BOOST_DEFAULTED_FUNCTION(format_description(), {})
0092 
0093     format_description(format_description const& that) : literal_chars(that.literal_chars), format_elements(that.format_elements)
0094     {
0095     }
0096 
0097     format_description(BOOST_RV_REF(format_description) that) BOOST_NOEXCEPT
0098     {
0099         literal_chars.swap(that.literal_chars);
0100         format_elements.swap(that.format_elements);
0101     }
0102 
0103     format_description& operator= (format_description that) BOOST_NOEXCEPT
0104     {
0105         literal_chars.swap(that.literal_chars);
0106         format_elements.swap(that.format_elements);
0107         return *this;
0108     }
0109 };
0110 
0111 //! Parses format string
0112 template< typename CharT >
0113 BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end);
0114 
0115 //! Parses format string
0116 template< typename CharT >
0117 BOOST_FORCEINLINE format_description< CharT > parse_format(const CharT* begin)
0118 {
0119     return parse_format(begin, begin + std::char_traits< CharT >::length(begin));
0120 }
0121 
0122 //! Parses format string
0123 template< typename CharT, typename TraitsT, typename AllocatorT >
0124 BOOST_FORCEINLINE format_description< CharT > parse_format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt)
0125 {
0126     const CharT* begin = fmt.c_str();
0127     return parse_format(begin, begin + fmt.size());
0128 }
0129 
0130 //! Formatter object
0131 template< typename CharT >
0132 class basic_format
0133 {
0134 public:
0135     //! Character type
0136     typedef CharT char_type;
0137     //! String type
0138     typedef std::basic_string< char_type > string_type;
0139     //! Stream type
0140     typedef basic_formatting_ostream< char_type > stream_type;
0141     //! Format description type
0142     typedef format_description< char_type > format_description_type;
0143 
0144     //! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream.
0145     class pump;
0146     friend class pump;
0147 
0148 private:
0149     //! Formatting params for a single placeholder in the format string
0150     struct formatting_params
0151     {
0152         //! Formatting element index in the format description
0153         unsigned int element_idx;
0154         //! Formatting result
0155         string_type target;
0156 
0157         formatting_params() : element_idx(~0u) {}
0158     };
0159     typedef std::vector< formatting_params > formatting_params_list;
0160 
0161 private:
0162     //! Format string description
0163     format_description_type m_format;
0164     //! Formatting parameters for all placeholders
0165     formatting_params_list m_formatting_params;
0166     //! Current formatting position
0167     unsigned int m_current_idx;
0168 
0169 public:
0170     //! Initializing constructor
0171     explicit basic_format(string_type const& fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
0172     {
0173         init_params();
0174     }
0175     //! Initializing constructor
0176     explicit basic_format(const char_type* fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0)
0177     {
0178         init_params();
0179     }
0180 
0181     //! Clears all formatted strings and resets the current formatting position
0182     void clear() BOOST_NOEXCEPT
0183     {
0184         for (typename formatting_params_list::iterator it = m_formatting_params.begin(), end = m_formatting_params.end(); it != end; ++it)
0185         {
0186             it->target.clear();
0187         }
0188         m_current_idx = 0;
0189     }
0190 
0191     //! Creates a pump that will receive all format arguments and put the formatted string into the stream
0192     pump make_pump(stream_type& strm)
0193     {
0194         // Flush the stream beforehand so that the pump can safely switch the stream storage string
0195         strm.flush();
0196         return pump(*this, strm);
0197     }
0198 
0199     //! Composes the final string from the formatted pieces
0200     string_type str() const
0201     {
0202         string_type result;
0203         compose(result);
0204         return BOOST_LOG_NRVO_RESULT(result);
0205     }
0206 
0207 private:
0208     //! Initializes the formatting params
0209     void init_params()
0210     {
0211         typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
0212         for (; it != end; ++it)
0213         {
0214             if (it->arg_number >= 0)
0215             {
0216                 if (static_cast< unsigned int >(it->arg_number) >= m_formatting_params.size())
0217                     m_formatting_params.resize(it->arg_number + 1);
0218                 m_formatting_params[it->arg_number].element_idx = static_cast< unsigned int >(it - m_format.format_elements.begin());
0219             }
0220         }
0221     }
0222 
0223     //! Composes the final string from the formatted pieces
0224     template< typename T >
0225     void compose(T& str) const
0226     {
0227         typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end();
0228         for (; it != end; ++it)
0229         {
0230             if (it->arg_number >= 0)
0231             {
0232                 // This is a placeholder
0233                 string_type const& target = m_formatting_params[it->arg_number].target;
0234                 str.append(target.data(), target.size());
0235             }
0236             else
0237             {
0238                 // This is a literal
0239                 const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos;
0240                 str.append(p, it->literal_len);
0241             }
0242         }
0243     }
0244 };
0245 
0246 //! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream.
0247 template< typename CharT >
0248 class basic_format< CharT >::pump
0249 {
0250     BOOST_MOVABLE_BUT_NOT_COPYABLE(pump)
0251 
0252 private:
0253     //! The guard temporarily replaces storage string in the specified stream
0254     struct scoped_storage
0255     {
0256         scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_state_backup(strm.rdbuf()->get_storage_state())
0257         {
0258             strm.attach(storage);
0259         }
0260         ~scoped_storage()
0261         {
0262             m_stream.rdbuf()->set_storage_state(m_storage_state_backup);
0263         }
0264 
0265     private:
0266         stream_type& m_stream;
0267         typename stream_type::streambuf_type::storage_state m_storage_state_backup;
0268     };
0269 
0270 private:
0271     //! Reference to the owner
0272     basic_format* m_owner;
0273     //! Reference to the stream
0274     stream_type* m_stream;
0275     //! Unhandled exception count
0276     const unsigned int m_exception_count;
0277 
0278 public:
0279     //! Initializing constructor
0280     pump(basic_format& owner, stream_type& strm) BOOST_NOEXCEPT : m_owner(&owner), m_stream(&strm), m_exception_count(boost::core::uncaught_exceptions())
0281     {
0282     }
0283 
0284     //! Move constructor
0285     pump(BOOST_RV_REF(pump) that) BOOST_NOEXCEPT : m_owner(that.m_owner), m_stream(that.m_stream), m_exception_count(that.m_exception_count)
0286     {
0287         that.m_owner = NULL;
0288         that.m_stream = NULL;
0289     }
0290 
0291     //! Destructor
0292     ~pump() BOOST_NOEXCEPT_IF(false)
0293     {
0294         if (m_owner)
0295         {
0296             // Whether or not the destructor is called because of an exception, the format object has to be cleared
0297             boost::log::aux::cleanup_guard< basic_format< char_type > > cleanup1(*m_owner);
0298 
0299             BOOST_ASSERT(m_stream != NULL);
0300             if (m_exception_count >= boost::core::uncaught_exceptions())
0301             {
0302                 // Compose the final string in the stream buffer
0303                 m_stream->flush();
0304                 m_owner->compose(*m_stream->rdbuf());
0305             }
0306         }
0307     }
0308 
0309     /*!
0310      * Puts an argument to the formatter. Note the pump has to be returned by value and not by reference in order this to
0311      * work with Boost.Phoenix expressions. Otherwise the pump that is returned from \c basic_format::make_pump is
0312      * destroyed after the first call to \c operator%, and the returned reference becomes dangling.
0313      */
0314     template< typename T >
0315     pump operator% (T const& val)
0316     {
0317         BOOST_ASSERT_MSG(m_owner != NULL && m_stream != NULL, "Boost.Log: This basic_format::pump has already been moved from");
0318 
0319         if (m_owner->m_current_idx < m_owner->m_formatting_params.size())
0320         {
0321             scoped_storage storage_guard(*m_stream, m_owner->m_formatting_params[m_owner->m_current_idx].target);
0322 
0323             *m_stream << val;
0324             m_stream->flush();
0325 
0326             ++m_owner->m_current_idx;
0327         }
0328 
0329         return boost::move(*this);
0330     }
0331 };
0332 
0333 } // namespace aux
0334 
0335 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0336 
0337 } // namespace boost
0338 
0339 #include <boost/log/detail/footer.hpp>
0340 
0341 #endif // BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_