File indexing completed on 2025-01-18 09:39:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
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
0050 typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
0051
0052 typedef std::basic_streambuf< CharT, TraitsT > base_type;
0053
0054
0055 enum { buffer_size = 16 };
0056
0057 public:
0058
0059 typedef typename base_type::char_type char_type;
0060
0061 typedef typename base_type::traits_type traits_type;
0062
0063 typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
0064
0065 typedef typename string_type::size_type size_type;
0066
0067 typedef typename base_type::int_type int_type;
0068
0069 struct storage_state
0070 {
0071
0072 string_type* storage;
0073
0074 size_type max_size;
0075
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
0085 storage_state m_storage_state;
0086
0087 char_type m_buffer[buffer_size];
0088
0089 public:
0090
0091 basic_ostringstreambuf() BOOST_NOEXCEPT
0092 {
0093 base_type::setp(m_buffer, m_buffer + (sizeof(m_buffer) / sizeof(*m_buffer)));
0094 }
0095
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
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
0118 void attach(string_type& storage)
0119 {
0120 attach(storage, storage.max_size());
0121 }
0122
0123
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
0132 string_type* storage() const BOOST_NOEXCEPT { return m_storage_state.storage; }
0133
0134
0135 size_type max_size() const BOOST_NOEXCEPT { return m_storage_state.max_size; }
0136
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
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
0160 bool storage_overflow() const BOOST_NOEXCEPT { return m_storage_state.overflow; }
0161
0162 void storage_overflow(bool f) BOOST_NOEXCEPT { m_storage_state.overflow = f; }
0163
0164
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
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
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
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
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
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
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
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
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
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
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
0298
0299
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
0306 if ((c & 0xFC00u) != 0xD800u)
0307 return pos + 1u;
0308 }
0309
0310 return 0u;
0311 }
0312
0313
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
0317 return max_size;
0318 }
0319
0320
0321 BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
0322
0323 BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
0324 };
0325
0326 }
0327
0328 BOOST_LOG_CLOSE_NAMESPACE
0329
0330 }
0331
0332 #include <boost/log/detail/footer.hpp>
0333
0334 #endif