libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
stream_util.hpp
1 #pragma once
2 
3 #include "fly/types/string/concepts.hpp"
4 #include "fly/types/string/literals.hpp"
5 
6 #include <cctype>
7 #include <ios>
8 #include <locale>
9 #include <ostream>
10 
11 namespace fly::detail {
12 
21 {
22 public:
28  explicit ScopedStreamModifiers(std::ostream &stream) noexcept;
29 
34 
40  void setf(std::ios_base::fmtflags flag);
41 
48  void setf(std::ios_base::fmtflags flag, std::ios_base::fmtflags mask);
49 
55  template <typename Facet>
56  void locale();
57 
63  void fill(char ch);
64 
70  void width(std::streamsize size);
71 
77  void precision(std::streamsize size);
78 
79 private:
81  ScopedStreamModifiers &operator=(const ScopedStreamModifiers &) = delete;
82 
83  std::ostream &m_stream;
84 
85  const std::ios_base::fmtflags m_flags;
86  bool m_changed_flags {false};
87 
88  const std::locale m_locale;
89  bool m_changed_locale {false};
90 
91  const char m_fill;
92  bool m_changed_fill {false};
93 
94  const std::streamsize m_width;
95  bool m_changed_width {false};
96 
97  const std::streamsize m_precision;
98  bool m_changed_precision {false};
99 };
100 
108 template <fly::StandardCharacter CharType>
109 class PositivePaddingFacet : public std::ctype<CharType>
110 {
111 protected:
112  CharType do_widen(char ch) const override;
113 
114  const char *do_widen(const char *begin, const char *end, CharType *dest) const override;
115 
116 private:
117  static constexpr const auto s_plus_sign = FLY_CHR(char, '+');
118  static constexpr const auto s_space = FLY_CHR(CharType, ' ');
119 };
120 
121 //==================================================================================================
122 inline ScopedStreamModifiers::ScopedStreamModifiers(std::ostream &stream) noexcept :
123  m_stream(stream),
124  m_flags(stream.flags()),
125  m_locale(stream.getloc()),
126  m_fill(stream.fill()),
127  m_width(stream.width()),
128  m_precision(stream.precision())
129 {
130 }
131 
132 //==================================================================================================
134 {
135  if (m_changed_flags)
136  {
137  m_stream.flags(m_flags);
138  }
139  if (m_changed_locale)
140  {
141  m_stream.imbue(m_locale);
142  }
143  if (m_changed_fill)
144  {
145  m_stream.fill(m_fill);
146  }
147  if (m_changed_width)
148  {
149  m_stream.width(m_width);
150  }
151  if (m_changed_precision)
152  {
153  m_stream.precision(m_precision);
154  }
155 }
156 
157 //==================================================================================================
158 inline void ScopedStreamModifiers::setf(std::ios_base::fmtflags flag)
159 {
160  m_stream.setf(flag);
161  m_changed_flags = true;
162 }
163 
164 //==================================================================================================
165 inline void ScopedStreamModifiers::setf(std::ios_base::fmtflags flag, std::ios_base::fmtflags mask)
166 {
167  m_stream.setf(flag, mask);
168  m_changed_flags = true;
169 }
170 
171 //==================================================================================================
172 template <typename Facet>
174 {
175  m_stream.imbue({m_stream.getloc(), new Facet()});
176  m_changed_locale = true;
177 }
178 
179 //==================================================================================================
180 inline void ScopedStreamModifiers::fill(char ch)
181 {
182  m_stream.fill(ch);
183  m_changed_fill = true;
184 }
185 
186 //==================================================================================================
187 inline void ScopedStreamModifiers::width(std::streamsize size)
188 {
189  m_stream.width(size);
190  m_changed_width = true;
191 }
192 
193 //==================================================================================================
194 inline void ScopedStreamModifiers::precision(std::streamsize size)
195 {
196  m_stream.precision(size);
197  m_changed_precision = true;
198 }
199 
200 //==================================================================================================
201 template <fly::StandardCharacter CharType>
202 CharType PositivePaddingFacet<CharType>::do_widen(char ch) const
203 {
204  return (ch == s_plus_sign) ? s_space : static_cast<CharType>(ch);
205 }
206 
207 //==================================================================================================
208 template <fly::StandardCharacter CharType>
209 const char *
210 PositivePaddingFacet<CharType>::do_widen(const char *begin, const char *end, CharType *dest) const
211 {
212  while (begin != end)
213  {
214  *dest++ = do_widen(*begin++);
215  }
216 
217  return end;
218 }
219 
220 } // namespace fly::detail
Definition: stream_util.hpp:110
Definition: stream_util.hpp:21
ScopedStreamModifiers(std::ostream &stream) noexcept
Definition: stream_util.hpp:122
void width(std::streamsize size)
Definition: stream_util.hpp:187
void setf(std::ios_base::fmtflags flag)
Definition: stream_util.hpp:158
void precision(std::streamsize size)
Definition: stream_util.hpp:194
~ScopedStreamModifiers()
Definition: stream_util.hpp:133
void fill(char ch)
Definition: stream_util.hpp:180
void locale()
Definition: stream_util.hpp:173