1 // -*- C++ -*-
2 /**
3 * @brief The class OSS streams out objects
4 *
5 * Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6 *
7 * This library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21 #ifndef OPENTURNS_OSS_HXX
22 #define OPENTURNS_OSS_HXX
23
24 #include <sstream>
25 #include <iterator>
26 #include <functional>
27 #include <utility> // for std::pair
28 #include "openturns/OStream.hxx"
29
30 BEGIN_NAMESPACE_OPENTURNS
31
32 template <typename U, typename V>
operator <<(std::ostream & os,const std::pair<U,V> & p)33 std::ostream & operator << (std::ostream & os, const std::pair<U, V> & p)
34 {
35 return os << "(" << p.first << "," << p.second << ")";
36 }
37
38 template <typename U, typename V>
operator <<(OStream & OS,const std::pair<U,V> & p)39 OStream & operator << (OStream & OS, const std::pair<U, V> & p)
40 {
41 return OS << "(" << p.first << "," << p.second << ")";
42 }
43
44
45
46 /**
47 * Struct Bulk protects the underlying object output from being
48 * modified by OSSFormater
49 */
50 template <class T>
51 struct Bulk
52 {
53 T data_;
BulkBulk54 Bulk(T data) : data_(data) {}
operator TBulk55 operator T() const
56 {
57 return data_;
58 }
59 };
60
61 /**
62 * Struct OSSFormater is a helper class for OSS that adapt the
63 * format of output according to type T
64 */
65
66 /* Any type */
67 template <class T>
68 struct OSSFormater
69 {
70 inline
71 static
applyOSSFormater72 void apply(std::ostringstream & oss, T obj, int /*precision*/)
73 {
74 oss << obj;
75 }
76
77 inline
78 static
applyOSSFormater79 void apply(OStream & OS, T obj, int /*precision*/)
80 {
81 OS << obj;
82 }
83 }; /* struct OSSFormater */
84
85 /* double */
86 template <>
87 struct OSSFormater<double>
88 {
89 inline
90 static
applyOSSFormater91 void apply(std::ostringstream & oss, double d, int precision)
92 {
93 int oldPrecision = static_cast<int>(oss.precision(precision));
94 oss << d;
95 oss.precision(oldPrecision);
96 }
97
98 inline
99 static
applyOSSFormater100 void apply(OStream & OS, double d, int precision)
101 {
102 int oldPrecision = static_cast<int>(OS.getStream().precision(precision));
103 OS.getStream() << d;
104 OS.getStream().precision(oldPrecision);
105 }
106 };
107
108 /* float */
109 template <>
110 struct OSSFormater<float>
111 {
112 inline
113 static
applyOSSFormater114 void apply(std::ostringstream & oss, float f, int precision)
115 {
116 int oldPrecision = static_cast<int>(oss.precision(precision));
117 oss << f;
118 oss.precision(oldPrecision);
119 }
120
121 inline
122 static
applyOSSFormater123 void apply(OStream & OS, float f, int precision)
124 {
125 int oldPrecision = static_cast<int>(OS.getStream().precision(precision));
126 OS.getStream() << f;
127 OS.getStream().precision(oldPrecision);
128 }
129 };
130
131 /* bool */
132 template <>
133 struct OSSFormater<bool>
134 {
135 inline
136 static
applyOSSFormater137 void apply(std::ostringstream & oss, bool b, int /*precision*/)
138 {
139 oss << (b ? "true" : "false");
140 }
141
142 inline
143 static
applyOSSFormater144 void apply(OStream & OS, bool b, int /*precision*/)
145 {
146 OS.getStream() << (b ? "true" : "false");
147 }
148 };
149
150
151
152
153
154
155 /**
156 * Class OSS is useful when streaming data through a function
157 * that expect a string as parameter
158 */
159 class OT_API OSS
160 {
161 private:
162 std::ostringstream oss_;
163 mutable int precision_;
164 mutable bool full_;
165
166 public:
167 explicit OSS(bool full = true);
168
169 template <class T>
170 inline
operator <<(T obj)171 OSS & operator << (T obj)
172 {
173 if (full_)
174 {
175 OStream OS(oss_);
176 OSSFormater<T>::apply(OS, obj, precision_);
177 }
178 else OSSFormater<T>::apply(oss_, obj, precision_);
179 return *this;
180 }
181
182 inline
setPrecision(int precision)183 OSS & setPrecision(int precision)
184 {
185 precision_ = precision;
186 oss_.precision(precision_);
187 return *this;
188 }
189
190 inline
getPrecision() const191 int getPrecision() const
192 {
193 precision_ = static_cast<int>(oss_.precision());
194 return precision_;
195 }
196
197 operator std::string() const;
198 std::string str() const;
199
200 void clear();
201
202 }; /* class OSS */
203
204 template <typename _Tp>
205 struct AllElementsPredicate : public std::unary_function<_Tp, Bool>
206 {
207 Bool
operator ()AllElementsPredicate208 operator()(const _Tp&) const
209 {
210 return true;
211 }
212 };
213
214 template < typename _Tp, typename _UnaryPredicate = AllElementsPredicate<_Tp>, typename _CharT = char,
215 typename _Traits = std::char_traits<_CharT> >
216 class OSS_iterator
217 : public std::iterator<std::output_iterator_tag, void, void, void, void>
218 {
219 public:
220 //@{
221 /// Public typedef
222 typedef _CharT char_type;
223 typedef _Traits traits_type;
224 typedef OSS ostream_type;
225 //@}
226
227 private:
228 ostream_type* _M_stream;
229 String _M_string;
230 String _M_prefix;
231 mutable bool _M_first;
232
233 public:
234 /**
235 * Construct from an ostream
236 *
237 * The delimiter string @a c is written to the stream after every Tp
238 * written to the stream. The delimiter is not copied, and thus must
239 * not be destroyed while this iterator is in use.
240 *
241 * @param s Underlying ostream to write to.
242 * @param c CharT delimiter string to insert.
243 */
OSS_iterator(ostream_type & __s,const String & __c="",const String & __p="")244 OSS_iterator(ostream_type & __s, const String & __c = "", const String & __p = "")
245 : _M_stream(&__s)
246 , _M_string(__c)
247 , _M_prefix(__p)
248 , _M_first(true)
249 {}
250
251 /// Copy constructor.
OSS_iterator(const OSS_iterator & __obj)252 OSS_iterator(const OSS_iterator& __obj)
253 : _M_stream(__obj._M_stream)
254 , _M_string(__obj._M_string)
255 , _M_prefix(__obj._M_prefix)
256 , _M_first(__obj._M_first)
257 {}
258
259 /// Copy assignment
260 OSS_iterator&
operator =(const OSS_iterator & obj)261 operator=(const OSS_iterator& obj)
262 {
263 _M_stream = obj._M_stream;
264 _M_string = obj._M_string;
265 _M_prefix = obj._M_prefix;
266 _M_first = obj._M_first;
267 return *this;
268 }
269
270 /// Writes @a value to underlying ostream using operator<<. If
271 /// constructed with delimiter string, writes delimiter to ostream.
272 OSS_iterator&
operator =(const _Tp & value)273 operator=(const _Tp& value)
274 {
275 if (_UnaryPredicate()(value))
276 {
277 if (!_M_first) *_M_stream << _M_string;
278 *_M_stream << _M_prefix << value;
279 _M_first = false;
280 }
281 return *this;
282 }
283
284 OSS_iterator&
operator *()285 operator*()
286 {
287 return *this;
288 }
289
290 OSS_iterator&
operator ++()291 operator++()
292 {
293 return *this;
294 }
295
296 OSS_iterator
operator ++(int)297 operator++(int)
298 {
299 return *this;
300 }
301
302 };
303
304
305 END_NAMESPACE_OPENTURNS
306
307 #endif /* OPENTURNS_OSS_HXX */
308