Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2016.
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   attachable_sstream_buf.hpp
0009  * \author Andrey Semashev
0010  * \date   29.07.2007
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_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
0017 #define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
0018 
0019 #include <cstddef>
0020 #include <memory>
0021 #include <locale>
0022 #include <string>
0023 #include <streambuf>
0024 #include <boost/assert.hpp>
0025 #include <boost/cstdint.hpp>
0026 #include <boost/type_traits/integral_constant.hpp>
0027 #include <boost/log/detail/config.hpp>
0028 #include <boost/log/detail/header.hpp>
0029 
0030 #ifdef BOOST_HAS_PRAGMA_ONCE
0031 #pragma once
0032 #endif
0033 
0034 namespace boost {
0035 
0036 BOOST_LOG_OPEN_NAMESPACE
0037 
0038 namespace aux {
0039 
0040 //! A streambuf that puts the formatted data to an external string
0041 template<
0042     typename CharT,
0043     typename TraitsT = std::char_traits< CharT >,
0044     typename AllocatorT = std::allocator< CharT >
0045 >
0046 class basic_ostringstreambuf :
0047     public std::basic_streambuf< CharT, TraitsT >
0048 {
0049     //! Self type
0050     typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
0051     //! Base type
0052     typedef std::basic_streambuf< CharT, TraitsT > base_type;
0053 
0054     //! Buffer size
0055     enum { buffer_size = 16 };
0056 
0057 public:
0058     //! Character type
0059     typedef typename base_type::char_type char_type;
0060     //! Traits type
0061     typedef typename base_type::traits_type traits_type;
0062     //! String type
0063     typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
0064     //! Size type
0065     typedef typename string_type::size_type size_type;
0066     //! Int type
0067     typedef typename base_type::int_type int_type;
0068 
0069     struct storage_state
0070     {
0071         //! A reference to the string that will be filled
0072         string_type* storage;
0073         //! Max size of the storage, in characters
0074         size_type max_size;
0075         //! Indicates that storage overflow happened
0076         bool overflow;
0077 
0078         BOOST_CONSTEXPR storage_state() BOOST_NOEXCEPT : storage(NULL), max_size(0u), overflow(false)
0079         {
0080         }
0081     };
0082 
0083 private:
0084     //! Buffer storage state
0085     storage_state m_storage_state;
0086     //! A buffer used to temporarily store output
0087     char_type m_buffer[buffer_size];
0088 
0089 public:
0090     //! Constructor
0091     basic_ostringstreambuf() BOOST_NOEXCEPT
0092     {
0093         base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
0094     }
0095     //! Constructor
0096     explicit basic_ostringstreambuf(string_type& storage) BOOST_NOEXCEPT
0097     {
0098         base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
0099         attach(storage);
0100     }
0101 
0102     storage_state const& get_storage_state() const BOOST_NOEXCEPT { return m_storage_state; }
0103     void set_storage_state(storage_state const& st) BOOST_NOEXCEPT { m_storage_state = st; }
0104 
0105     //! Detaches the buffer from the string
0106     void detach()
0107     {
0108         if (m_storage_state.storage)
0109         {
0110             this_type::sync();
0111             m_storage_state.storage = NULL;
0112             m_storage_state.max_size = 0u;
0113             m_storage_state.overflow = false;
0114         }
0115     }
0116 
0117     //! Attaches the buffer to another string
0118     void attach(string_type& storage)
0119     {
0120         attach(storage, storage.max_size());
0121     }
0122 
0123     //! Attaches the buffer to another string
0124     void attach(string_type& storage, size_type max_size)
0125     {
0126         detach();
0127         m_storage_state.storage = &storage;
0128         this->max_size(max_size);
0129     }
0130 
0131     //! Returns a pointer to the attached string
0132     string_type* storage() const BOOST_NOEXCEPT { return m_storage_state.storage; }
0133 
0134     //! Returns the maximum size of the storage
0135     size_type max_size() const BOOST_NOEXCEPT { return m_storage_state.max_size; }
0136     //! Sets the maximum size of the storage
0137     void max_size(size_type size)
0138     {
0139         if (m_storage_state.storage)
0140         {
0141             const size_type storage_max_size = m_storage_state.storage->max_size();
0142             size = size > storage_max_size ? storage_max_size : size;
0143         }
0144 
0145         m_storage_state.max_size = size;
0146         ensure_max_size();
0147     }
0148     //! Makes sure the storage does not exceed the max size limit. Should be called after the storage is modified externally.
0149     void ensure_max_size()
0150     {
0151         if (m_storage_state.storage && m_storage_state.storage->size() > m_storage_state.max_size)
0152         {
0153             const size_type len = length_until_boundary(m_storage_state.storage->c_str(), m_storage_state.storage->size(), m_storage_state.max_size);
0154             m_storage_state.storage->resize(len);
0155             m_storage_state.overflow = true;
0156         }
0157     }
0158 
0159     //! Returns true if the max size limit has been exceeded
0160     bool storage_overflow() const BOOST_NOEXCEPT { return m_storage_state.overflow; }
0161     //! Sets the overflow flag
0162     void storage_overflow(bool f) BOOST_NOEXCEPT { m_storage_state.overflow = f; }
0163 
0164     //! Returns the size left in the storage
0165     size_type size_left() const BOOST_NOEXCEPT
0166     {
0167         BOOST_ASSERT(m_storage_state.storage != NULL);
0168 
0169         const size_type size = m_storage_state.storage->size();
0170         return size < m_storage_state.max_size ? m_storage_state.max_size - size : static_cast< size_type >(0u);
0171     }
0172 
0173     //! Appends a string to the storage and returns the number of written characters
0174     size_type append(const char_type* s, size_type n)
0175     {
0176         if (!m_storage_state.overflow)
0177         {
0178             BOOST_ASSERT(m_storage_state.storage != NULL);
0179 
0180             size_type left = size_left();
0181             BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
0182             if (BOOST_LIKELY(n <= left))
0183             {
0184                 m_storage_state.storage->append(s, n);
0185                 return n;
0186             }
0187             else
0188             {
0189                 // We have to find out where the last character that fits before the limit ends
0190                 left = length_until_boundary(s, n, left);
0191                 m_storage_state.storage->append(s, left);
0192                 m_storage_state.overflow = true;
0193                 return left;
0194             }
0195         }
0196         return 0u;
0197     }
0198 
0199     //! Appends the specified number of characters to the storage and returns the number of written characters
0200     size_type append(size_type n, char_type c)
0201     {
0202         if (!m_storage_state.overflow)
0203         {
0204             BOOST_ASSERT(m_storage_state.storage != NULL);
0205 
0206             const size_type left = size_left();
0207             BOOST_LOG_ASSUME(left <= m_storage_state.storage->max_size());
0208             if (BOOST_LIKELY(n <= left))
0209             {
0210                 m_storage_state.storage->append(n, c);
0211                 return n;
0212             }
0213             else
0214             {
0215                 m_storage_state.storage->append(left, c);
0216                 m_storage_state.overflow = true;
0217                 return left;
0218             }
0219         }
0220         return 0u;
0221     }
0222 
0223     //! Appends a character to the storage and returns the number of written characters
0224     size_type push_back(char_type c)
0225     {
0226         if (!m_storage_state.overflow)
0227         {
0228             BOOST_ASSERT(m_storage_state.storage != NULL);
0229 
0230             BOOST_LOG_ASSUME(m_storage_state.max_size <= m_storage_state.storage->max_size());
0231             if (BOOST_LIKELY(m_storage_state.storage->size() < m_storage_state.max_size))
0232             {
0233                 m_storage_state.storage->push_back(c);
0234                 return 1u;
0235             }
0236             else
0237             {
0238                 m_storage_state.overflow = true;
0239                 return 0u;
0240             }
0241         }
0242         return 0u;
0243     }
0244 
0245 protected:
0246     //! Puts all buffered data to the string
0247     int sync() BOOST_OVERRIDE
0248     {
0249         char_type* pBase = this->pbase();
0250         char_type* pPtr = this->pptr();
0251         if (pBase != pPtr)
0252         {
0253             this->append(pBase, static_cast< size_type >(pPtr - pBase));
0254             this->pbump(static_cast< int >(pBase - pPtr));
0255         }
0256         return 0;
0257     }
0258     //! Puts an unbuffered character to the string
0259     int_type overflow(int_type c) BOOST_OVERRIDE
0260     {
0261         this_type::sync();
0262         if (!traits_type::eq_int_type(c, traits_type::eof()))
0263         {
0264             this->push_back(traits_type::to_char_type(c));
0265             return c;
0266         }
0267         else
0268             return traits_type::not_eof(c);
0269     }
0270     //! Puts a character sequence to the string
0271     std::streamsize xsputn(const char_type* s, std::streamsize n) BOOST_OVERRIDE
0272     {
0273         this_type::sync();
0274         return static_cast< std::streamsize >(this->append(s, static_cast< size_type >(n)));
0275     }
0276 
0277     //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
0278     size_type length_until_boundary(const char_type* s, size_type n, size_type max_size) const
0279     {
0280         BOOST_ASSERT(max_size <= n);
0281         return length_until_boundary(s, n, max_size, boost::integral_constant< std::size_t, sizeof(char_type) >());
0282     }
0283 
0284 private:
0285     //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
0286     size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, boost::integral_constant< std::size_t, 1u >) const
0287     {
0288         std::locale loc = this->getloc();
0289         std::codecvt< wchar_t, char, std::mbstate_t > const& fac = std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(loc);
0290         std::mbstate_t mbs = std::mbstate_t();
0291         return static_cast< size_type >(fac.length(mbs, s, s + max_size, n));
0292     }
0293 
0294     //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
0295     static size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, boost::integral_constant< std::size_t, 2u >)
0296     {
0297         // Note: Although it's not required to be true for wchar_t, here we assume that the string has Unicode encoding (UTF-16 or UCS-2).
0298         // Compilers use some version of Unicode for wchar_t on all tested platforms, and std::locale doesn't offer a way
0299         // to find the character boundary for character types other than char anyway.
0300         size_type pos = max_size;
0301         while (pos > 0u)
0302         {
0303             --pos;
0304             uint_fast16_t c = static_cast< uint_fast16_t >(s[pos]);
0305             // Check if this is a leading surrogate
0306             if ((c & 0xFC00u) != 0xD800u)
0307                 return pos + 1u;
0308         }
0309 
0310         return 0u;
0311     }
0312 
0313     //! Finds the string length so that it includes only complete characters, and does not exceed \a max_size
0314     static size_type length_until_boundary(const char_type* s, size_type n, size_type max_size, boost::integral_constant< std::size_t, 4u >)
0315     {
0316         // In UTF-32 and UCS-4 one code point is encoded as one code unit
0317         return max_size;
0318     }
0319 
0320     //! Copy constructor (closed)
0321     BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
0322     //! Assignment (closed)
0323     BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
0324 };
0325 
0326 } // namespace aux
0327 
0328 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0329 
0330 } // namespace boost
0331 
0332 #include <boost/log/detail/footer.hpp>
0333 
0334 #endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_