• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright 2019 Glen Joseph Fernandes
3 (glenjofe@gmail.com)
4 
5 Distributed under the Boost Software License, Version 1.0.
6 (http://www.boost.org/LICENSE_1_0.txt)
7 */
8 #ifndef BOOST_UTILITY_OSTREAM_STRING_HPP
9 #define BOOST_UTILITY_OSTREAM_STRING_HPP
10 
11 #include <boost/config.hpp>
12 #include <iosfwd>
13 #include <cstddef>
14 
15 namespace boost {
16 namespace detail {
17 
18 template<class charT, class traits>
19 inline std::size_t
oss_put(std::basic_ostream<charT,traits> & os,const charT * data,std::size_t size)20 oss_put(std::basic_ostream<charT, traits>& os, const charT* data,
21     std::size_t size)
22 {
23     return static_cast<std::size_t>(os.rdbuf()->sputn(data, size));
24 }
25 
26 template<class charT, class traits>
27 inline bool
oss_fill(std::basic_ostream<charT,traits> & os,std::size_t size)28 oss_fill(std::basic_ostream<charT, traits>& os, std::size_t size)
29 {
30     charT c = os.fill();
31     charT fill[] = { c, c, c, c, c, c, c, c };
32     enum {
33         chunk = sizeof fill / sizeof(charT)
34     };
35     for (; size > chunk; size -= chunk) {
36         if (boost::detail::oss_put(os, fill, chunk) != chunk) {
37             return false;
38         }
39     }
40     return boost::detail::oss_put(os, fill, size) == size;
41 }
42 
43 template<class charT, class traits>
44 class oss_guard {
45 public:
oss_guard(std::basic_ostream<charT,traits> & os)46     explicit oss_guard(std::basic_ostream<charT, traits>& os) BOOST_NOEXCEPT
47         : os_(&os) { }
BOOST_NOEXCEPT_IF(false)48     ~oss_guard() BOOST_NOEXCEPT_IF(false) {
49         if (os_) {
50             os_->setstate(std::basic_ostream<charT, traits>::badbit);
51         }
52     }
release()53     void release() BOOST_NOEXCEPT {
54         os_ = 0;
55     }
56 private:
57     oss_guard(const oss_guard&);
58     oss_guard& operator=(const oss_guard&);
59     std::basic_ostream<charT, traits>* os_;
60 };
61 
62 } /* detail */
63 
64 template<class charT, class traits>
65 inline std::basic_ostream<charT, traits>&
ostream_string(std::basic_ostream<charT,traits> & os,const charT * data,std::size_t size)66 ostream_string(std::basic_ostream<charT, traits>& os, const charT* data,
67     std::size_t size)
68 {
69     typedef std::basic_ostream<charT, traits> stream;
70     detail::oss_guard<charT, traits> guard(os);
71     typename stream::sentry entry(os);
72     if (entry) {
73         std::size_t width = static_cast<std::size_t>(os.width());
74         if (width <= size) {
75             if (detail::oss_put(os, data, size) != size) {
76                 return os;
77             }
78         } else if ((os.flags() & stream::adjustfield) == stream::left) {
79             if (detail::oss_put(os, data, size) != size ||
80                 !detail::oss_fill(os, width - size)) {
81                 return os;
82             }
83         } else if (!detail::oss_fill(os, width - size) ||
84             detail::oss_put(os, data, size) != size) {
85             return os;
86         }
87         os.width(0);
88     }
89     guard.release();
90     return os;
91 }
92 
93 } /* boost */
94 
95 #endif
96