Doxygen
Loading...
Searching...
No Matches
textstream.h
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2021 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#ifndef TEXTSTREAM_H
17#define TEXTSTREAM_H
18
19#include <string>
20#include <iostream>
21#include <sstream>
22#include <cstdint>
23#include <cstdio>
24#include <fstream>
25#include <type_traits>
26
27#include "qcstring.h"
28#include "construct.h"
29
30/** @brief Text streaming class that buffers data.
31 *
32 * Simpler version of std::ostringstream that has much better
33 * performance.
34 */
35class TextStream final
36{
37 static const int INITIAL_CAPACITY = 4096;
38 public:
39 /** Creates an empty stream object.
40 */
41 explicit TextStream(size_t capacity = INITIAL_CAPACITY)
42 {
43 m_buffer.reserve(capacity);
44 }
45 /** Create a text stream object for writing to a std::ostream.
46 * @note data is buffered until flush() is called or the object is destroyed.
47 */
48 explicit TextStream(std::ostream *s) : m_s(s)
49 {
51 }
52 /** Create a text stream, initializing the buffer with string \a s
53 */
54 explicit TextStream(const std::string &s) : m_buffer(s)
55 {
56 m_buffer.reserve(s.length()+INITIAL_CAPACITY);
57 }
58
59 /** Writes any data that is buffered to the attached std::ostream */
61
63
64 /** Sets or changes the std::ostream to write to.
65 * @note Any data already buffered will be flushed.
66 */
67 void setStream(std::ostream *s)
68 {
69 flush();
70 m_s = s;
71 m_f = nullptr;
72 }
73
74 void setFile(FILE *f)
75 {
76 flush();
77 m_s = nullptr;
78 m_f = f;
79 }
80
81 /** Returns the attached std::ostream object.
82 * @see setStream()
83 */
84 std::ostream *stream() const
85 {
86 return m_s;
87 }
88
89 FILE *file() const
90 {
91 return m_f;
92 }
93
94 /** Adds a character to the stream */
96 {
97 m_buffer+=c;
98 return static_cast<TextStream&>(*this);
99 }
100 /** Adds an unsigned character to the stream */
101 TextStream &operator<<( unsigned char c)
102 {
103 m_buffer+=c;
104 return static_cast<TextStream&>(*this);
105 }
106
107 /** Adds an unsigned character string to the stream */
108 TextStream &operator<<( unsigned char *s)
109 {
110 if (s)
111 {
112 unsigned char *p = s;
113 while(*p)
114 {
115 m_buffer+=*p;
116 p++;
117 }
118 }
119 return static_cast<TextStream&>(*this);
120 }
121
122 /** Adds a C-style string to the stream */
123 TextStream &operator<<( const char *s)
124 {
125 if (s) m_buffer+=s;
126 return static_cast<TextStream&>(*this);
127 }
128
129 /** Adds a QCString to the stream */
130 TextStream &operator<<( const QCString &s )
131 {
132 m_buffer+=s.str();
133 return static_cast<TextStream&>(*this);
134 }
135
136 /** Adds a std::string to the stream */
137 TextStream &operator<<( const std::string &s )
138 {
139 m_buffer+=s;
140 return static_cast<TextStream&>(*this);
141 }
142
143 /** Adds a signed short integer to the stream */
144 TextStream &operator<<( signed short i)
145 {
146 output_int32(i,i<0);
147 return static_cast<TextStream&>(*this);
148 }
149
150 /** Adds a unsigned short integer to the stream */
151 TextStream &operator<<( unsigned short i)
152 {
153 output_int32(i,false);
154 return static_cast<TextStream&>(*this);
155 }
156
157 /** Adds a signed integer to the stream */
158 TextStream &operator<<( signed int i)
159 {
160 output_int32(i,i<0);
161 return static_cast<TextStream&>(*this);
162 }
163
164 /** Adds a unsigned integer to the stream */
165 TextStream &operator<<( unsigned int i)
166 {
167 output_int32(i,false);
168 return static_cast<TextStream&>(*this);
169 }
170
171 /** Adds a size_t integer to the stream.
172 * We use SFINAE to avoid a compiler error in case size_t already matches the 'unsigned int' overload.
173 */
174 template<typename T,
175 typename std::enable_if<std::is_same<T,size_t>::value,T>::type* = nullptr
176 >
178 {
179 output_int32(static_cast<uint32_t>(i),false);
180 return static_cast<TextStream&>(*this);
181 }
182
183 /** Adds a float to the stream */
185 {
186 output_double(static_cast<double>(f));
187 return static_cast<TextStream&>(*this);
188 }
189
190 /** Adds a double to the stream */
192 {
193 output_double(d);
194 return static_cast<TextStream&>(*this);
195 }
196
197 /** Adds a array of character to the stream
198 * @param buf the character buffer
199 * @param len the number of characters in the buffer to write
200 */
201 void write(const char *buf,size_t len)
202 {
203 m_buffer.append(buf,len);
204 }
205
206 /** Flushes the buffer. If a std::ostream is attached, the buffer's
207 * contents will be written to the stream.
208 */
209 void flush()
210 {
211 if (m_s)
212 {
213 m_s->write(m_buffer.c_str(),m_buffer.length());
214 }
215 else if (m_f)
216 {
217 fwrite(m_buffer.c_str(),1,m_buffer.length(),m_f);
218 }
219 m_buffer.clear();
220 }
221
222 /** Clears any buffered data */
223 void clear()
224 {
225 m_buffer.clear();
226 }
227
228 /** Return the contents of the buffer as a std::string object */
229 std::string str() const
230 {
231 return m_buffer;
232 }
233
234 /** Sets the buffer's contents to string \a s.
235 * Any data already in the buffer will be flushed.
236 */
237 void str(const std::string &s)
238 {
239 flush();
240 m_buffer=s;
241 }
242
243 /** Sets the buffer's contents to string \a s
244 * Any data already in the buffer will be flushed.
245 */
246 void str(const char *s)
247 {
248 flush();
249 if (s) m_buffer=s;
250 }
251
252 /** Returns true iff the buffer is empty */
253 bool empty() const
254 {
255 return m_buffer.empty();
256 }
257
258 private:
259 /** Writes a string representation of an integer to the buffer
260 * @param n the absolute value of the integer
261 * @param neg indicates if the integer is negative
262 */
263 void output_int32( uint32_t n, bool neg )
264 {
265 char buf[20];
266 char *p = &buf[19];
267 *p = '\0';
268 if ( neg )
269 {
270 n = static_cast<uint32_t>(-static_cast<int32_t>(n));
271 }
272 do { *--p = (static_cast<char>(n%10)) + '0'; n /= 10; } while ( n );
273 if ( neg ) *--p = '-';
274 m_buffer+=p;
275 }
276 void output_double( double d)
277 {
278 char buf[64];
279 snprintf(buf,64,"%f",d);
280 m_buffer+=buf;
281 }
282 std::string m_buffer;
283 std::ostream *m_s = nullptr;
284 FILE *m_f = nullptr;
285};
286
287#endif
const std::string & str() const
Definition qcstring.h:526
bool empty() const
Returns true iff the buffer is empty.
Definition textstream.h:253
TextStream & operator<<(unsigned char *s)
Adds an unsigned character string to the stream.
Definition textstream.h:108
void setStream(std::ostream *s)
Sets or changes the std::ostream to write to.
Definition textstream.h:67
std::ostream * stream() const
Returns the attached std::ostream object.
Definition textstream.h:84
TextStream & operator<<(const std::string &s)
Adds a std::string to the stream.
Definition textstream.h:137
void output_double(double d)
Definition textstream.h:276
TextStream & operator<<(float f)
Adds a float to the stream.
Definition textstream.h:184
TextStream & operator<<(unsigned short i)
Adds a unsigned short integer to the stream.
Definition textstream.h:151
void output_int32(uint32_t n, bool neg)
Writes a string representation of an integer to the buffer.
Definition textstream.h:263
TextStream & operator<<(signed int i)
Adds a signed integer to the stream.
Definition textstream.h:158
std::string m_buffer
Definition textstream.h:282
TextStream & operator<<(double d)
Adds a double to the stream.
Definition textstream.h:191
TextStream & operator<<(T i)
Adds a size_t integer to the stream.
Definition textstream.h:177
TextStream(const std::string &s)
Create a text stream, initializing the buffer with string s.
Definition textstream.h:54
void str(const std::string &s)
Sets the buffer's contents to string s.
Definition textstream.h:237
TextStream & operator<<(const QCString &s)
Adds a QCString to the stream.
Definition textstream.h:130
TextStream & operator<<(signed short i)
Adds a signed short integer to the stream.
Definition textstream.h:144
TextStream & operator<<(const char *s)
Adds a C-style string to the stream.
Definition textstream.h:123
FILE * m_f
Definition textstream.h:284
void flush()
Flushes the buffer.
Definition textstream.h:209
TextStream(std::ostream *s)
Create a text stream object for writing to a std::ostream.
Definition textstream.h:48
std::ostream * m_s
Definition textstream.h:283
void write(const char *buf, size_t len)
Adds a array of character to the stream.
Definition textstream.h:201
FILE * file() const
Definition textstream.h:89
~TextStream()
Writes any data that is buffered to the attached std::ostream.
Definition textstream.h:60
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
void str(const char *s)
Sets the buffer's contents to string s Any data already in the buffer will be flushed.
Definition textstream.h:246
TextStream(size_t capacity=INITIAL_CAPACITY)
Creates an empty stream object.
Definition textstream.h:41
static const int INITIAL_CAPACITY
Definition textstream.h:37
TextStream & operator<<(unsigned char c)
Adds an unsigned character to the stream.
Definition textstream.h:101
void setFile(FILE *f)
Definition textstream.h:74
TextStream & operator<<(char c)
Adds a character to the stream.
Definition textstream.h:95
void clear()
Clears any buffered data.
Definition textstream.h:223
TextStream & operator<<(unsigned int i)
Adds a unsigned integer to the stream.
Definition textstream.h:165
#define ONLY_DEFAULT_MOVABLE(cls)
Macro to help implementing the rule of 5 for a class that can be moved but not copied.
Definition construct.h:44