CACAO
OStream.hpp
Go to the documentation of this file.
1 /* src/toolbox/OStream.hpp - simple output stream
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 #ifndef OSTREAM_HPP_
26 #define OSTREAM_HPP_ 1
27 
28 #include <string>
29 #include <cstdio>
30 
31 namespace cacao {
32 
33 class OStream;
34 
35 OStream& out();
36 OStream& err();
37 
38 class SetWidth;
39 class SetZero;
40 class SetPrecision;
41 class SetIndent;
42 class SetPrefix;
43 
44 class FillZero;
45 
46 class Left;
47 class Right;
48 class Dec;
49 class Oct;
50 class Hex;
51 class FloatDec;
52 class Scientific;
53 class FloatHex;
54 class Indent;
55 class Dedent;
56 class Nl;
57 class Flush;
58 
59 class ThreadId;
60 
61 // ANSI terminal control
62 
63 enum Color {
66  Red,
81 };
82 
83 class ResetColor {};
84 class Bold {};
85 class NoBold {};
86 class Underline {};
87 class NoUnderline {};
88 
89 /** Simple stream class for formatted output
90  *
91  * This class is designed for debugging, thus usability trumps performance.
92  * It mostly mimics the iostreams library, but requires no global constructors.
93  * Interally everything is forwarded to stdio
94  *
95  * A stream can contain a prefix or intentions.
96  * The stream does not detect if your output contains a '\n' (newline) character.
97  * You must use the manipulator #nl instead. It works like std::endl but
98  * does not flush the stream.
99  *
100  * Simple examples :
101  * @code
102  * OStream os(stdout);
103  *
104  * os << "Hi there, my name is " << bold << "cacao" << nobold << nl;
105  * os << "I was born in " << 1996 << nl;
106  * os << "Test failures are " << underline << red << "BAD" << reset_color << nl;
107  * os << nl;
108  * os << "Do you like hex? " << hex << 255 << dec << nl;
109  * os << "Or floating point hex? " << float_hex << 17.3 << float_dec << nl;
110  * @endcode
111  *
112  * Unlike a std::iostream you can copy construct an OStream.
113  * A copied OStream will write to the same file but has it's own set of
114  * format flags that you can set independent of the original stream.
115  * But Colors, bold and underline are shared by all streams for a file,
116  * because they are stored in the underlying terminal.
117  * You should not write nl to the copied stream since the original will not
118  * detect the newline.
119  *
120  * Example:
121  * @code
122  * struct MyLittlePony {
123  * const char *name;
124  * Color color;
125  * };
126  *
127  * OStream& operator<<(OStream& os, const MyLittlePony& mlp) {
128  * OStream os2 = os; // new stream with new flags
129  *
130  * os2 << mlp.color;
131  * os2 << "My little pony is called " << setw(20) << right << mlp.name;
132  * os2 << hex;
133  *
134  * // Forgot to unset hex for os2: no problem, hex flag is not shared
135  * // Forgot to unset color: big problem, colors are shared!
136  *
137  * return os; // always return original stream
138  * }
139  * @endcode
140  */
141 class OStream {
142 public:
143  /// create a new stream with default flags
144  OStream(FILE *file);
145 
146  /** copy stream
147  *
148  * creates a new stream with the same file
149  * but default
150  */
151  OStream(const OStream&);
152 
153  OStream& operator<<(char);
154  OStream& operator<<(bool);
155  OStream& operator<<(long);
156  OStream& operator<<(unsigned long);
157  OStream& operator<<(long long );
158  OStream& operator<<(unsigned long long);
159  OStream& operator<<(double);
160  OStream& operator<<(const void*);
161  OStream& operator<<(const char*);
162 
163  OStream& operator<<(unsigned int n) {
164  return this->operator<<(static_cast<unsigned long>(n));
165  }
166 
167  OStream& operator<<(int n) {
168  return this->operator<<(static_cast<long>(n));
169  }
170 
171  // manipulators
172  OStream& operator<<(const SetWidth&);
173  OStream& operator<<(const SetZero&);
175  OStream& operator<<(const SetIndent&);
176  OStream& operator<<(const SetPrefix&);
177 
178  OStream& operator<<(const FillZero&);
179 
180  OStream& operator<<(const Left&);
181  OStream& operator<<(const Right&);
182 
183  OStream& operator<<(const Dec&);
184  OStream& operator<<(const Oct&);
185  OStream& operator<<(const Hex&);
186 
187  OStream& operator<<(const FloatDec&);
188  OStream& operator<<(const Scientific&);
189  OStream& operator<<(const FloatHex&);
190 
191  OStream& operator<<(const Indent&);
192  OStream& operator<<(const Dedent&);
193 
194  OStream& operator<<(const Nl&);
195  OStream& operator<<(const Flush&);
196 
197  OStream& operator<<(const ThreadId&);
198 
199  // ANSI codes
201 
202  OStream& operator<<(const ResetColor&);
203 
204  OStream& operator<<(const Bold&);
205  OStream& operator<<(const NoBold&);
206  OStream& operator<<(const Underline&);
207  OStream& operator<<(const NoUnderline&);
208 
209  void set_file(FILE *file) { this->file = file; }
210 
211  /// force color (0 = disabled, 1 = yes, 0 = no)
212  static void set_force_color(int);
213 private:
214  void on_newline();
215 
216  /// initialize all format flags to their default value
217  void init_flag_defaults();
218 
219  /// initialize all flags that only apply to one write operation
220  void init_transient_flags();
221  /// initialize all flags that survive a write operation
222  void init_persistent_flags();
223 
224  /// file stream writes to
225  FILE *file;
226 
227  /// true iff we are at the beginning of a new line
228  bool newline;
229 
230  /// supports ansi escape codes
232 
233  /// supports ansi escape codes
234  bool use_color() const;
235 
236  /// force color (0 = disabled, 1 = yes, 0 = no)
237  static int force_color;
238 
243  };
244  enum FloatFormat {
248  };
249 
250  // ********** format flags
251 
252  /** padding for next write
253  *
254  * ! width is reset to zero by all standard write operations !
255  *
256  * default value is 0
257  */
258  size_t width;
259 
260  /** precision
261  *
262  * ! precision is reset to -1 by all standard write operations !
263  *
264  * default value is -1 (i.e. turned off)
265  */
267 
268  /** fill_zero
269  *
270  * ! fill_zero is reset to false by all standard write operations !
271  *
272  * default value is false
273  */
274  bool fill_zero;
275 
276  /** Alignment to use when padding text
277  *
278  * default value is OStream::Align_right
279  */
280  enum {
283  } align;
284 
285  /** format used to print integer types
286  *
287  * default value is \link OStream::IntegerFormat::IntFmt_decimal decimal \endlink
288  */
290 
291  /** format used to print floating point types
292  *
293  * default value is \link OStream::FloatFormat::FloatFmt_decimal decimal \endlink
294  */
296 
297  /** indentation level
298  *
299  * every new line will start with OStream::Flags::indent_lvl * 4 spaces
300  *
301  * default value is 0
302  */
303  size_t indent_lvl;
304 
305  /** line prefix
306  *
307  * ignored if NULL
308  * will be printed at start of every new line
309  *
310  * default value is NULL
311  */
312  const char *prefix;
313 
314  /** color line prefix is printed in
315  *
316  * ignored if negative
317  *
318  * default value is -1
319  */
321 
322  friend class Logging;
323 };
324 
325 /// Set width flag for next item to be written.
326 class SetWidth {
327  size_t width;
328 public:
329  SetWidth(size_t width) : width(width) {}
330 
331 friend class OStream;
332 };
333 
334 /// Set width flag and fill zero for next item to be written.
335 class SetZero {
336  size_t width;
337 public:
338  SetZero(size_t width) : width(width) {}
339 
340 friend class OStream;
341 };
342 
343 /// Set precision flag for next item to be written.
346 public:
347  SetPrecision(int precision) : precision(precision) {}
348 
349 friend class OStream;
350 };
351 
352 /// Set indent level in stream
353 class SetIndent {
354  size_t indent;
355 public:
356  SetIndent(size_t indent) : indent(indent) {}
357 
358 friend class OStream;
359 };
360 
361 /// Set stream prefix
362 class SetPrefix {
363  const char *prefix;
365 public:
366  SetPrefix(const char *prefix, Color color)
367  : prefix(prefix), color(color) {}
368 
369 friend class OStream;
370 };
371 
372 class FillZero {};
373 
374 class Left {};
375 class Right {};
376 class Dec {};
377 class Oct {};
378 class Hex {};
379 class FloatDec {};
380 class Scientific {};
381 class FloatHex {};
382 class Indent {};
383 class Dedent {};
384 class Nl {};
385 class Flush {};
386 
387 class ThreadId {};
388 
389 class ResetColor;
390 class Bold;
391 class NoBold;
392 class Underline;
393 class NoUnderline;
394 
395 inline static SetWidth setw(size_t w) {
396  return SetWidth(w);
397 }
398 inline static SetZero setz(size_t w) {
399  return SetZero(w);
400 }
401 inline static SetPrecision setprecision(int p) {
402  return SetPrecision(p);
403 }
404 inline static SetIndent setindent(size_t i) {
405  return SetIndent(i);
406 }
407 inline static SetPrefix setprefix(const char *prefix, Color color) {
408  return SetPrefix(prefix, color);
409 }
410 
411 extern FillZero fillzero;
412 extern Left left;
413 extern Right right;
414 extern Dec dec;
415 extern Oct oct;
416 extern Hex hex;
417 extern FloatDec float_dec;
418 extern Scientific scientific;
419 extern FloatHex float_hex;
420 extern Indent indent;
421 extern Dedent dedent;
422 extern Nl nl;
423 extern Flush flush;
424 
425 // pipe this into a stream to print the current thread's id
426 extern ThreadId threadid;
427 
428 extern ResetColor reset_color;
429 extern Bold bold;
430 extern NoBold nobold;
431 extern Underline underline;
432 extern NoUnderline nounderline;
433 
434 // helper templates
435 template <class _ForwardIterator>
436 inline OStream& print_container(OStream &OS, _ForwardIterator i, const _ForwardIterator &e) {
437  if (i == e)
438  return OS << "[<empty>]";
439  OS << "[" << *i;
440  ++i;
441  for( ; i != e ; ++i) {
442  OS << ", " << *i;
443  }
444  return OS << "]";
445 }
446 
447 template <class _ForwardIterator>
448 inline OStream& print_ptr_container(OStream &OS, _ForwardIterator i, const _ForwardIterator &e) {
449  if (i == e)
450  return OS << "[<empty>]";
451  OS << "[" << **i;
452  ++i;
453  for( ; i != e ; ++i) {
454  OS << ", " << **i;
455  }
456  return OS << "]";
457 }
458 
459 inline OStream& operator<<(OStream &OS, const std::string &t) {
460  return OS << t.c_str();
461 }
462 
463 } // end namespace cacao
464 
465 #endif // OSTREAM_HPP_
466 
467 
468 /*
469  * These are local overrides for various environment variables in Emacs.
470  * Please do not remove this and leave it at the end of the file, where
471  * Emacs will automagically detect them.
472  * ---------------------------------------------------------------------
473  * Local variables:
474  * mode: c++
475  * indent-tabs-mode: t
476  * c-basic-offset: 4
477  * tab-width: 4
478  * End:
479  * vim:noexpandtab:sw=4:ts=4:
480  */
size_t indent_lvl
indentation level
Definition: OStream.hpp:303
FloatDec float_dec
Definition: OStream.cpp:51
static SetWidth setw(size_t w)
Definition: OStream.hpp:395
IntegerFormat int_fmt
format used to print integer types
Definition: OStream.hpp:289
size_t width
Definition: OStream.hpp:336
OStream & operator<<(int n)
Definition: OStream.hpp:167
Set precision flag for next item to be written.
Definition: OStream.hpp:344
SetZero(size_t width)
Definition: OStream.hpp:338
Set stream prefix.
Definition: OStream.hpp:362
OStream & print_container(OStream &OS, _ForwardIterator i, const _ForwardIterator &e)
Definition: OStream.hpp:436
OStream & operator<<(unsigned int n)
Definition: OStream.hpp:163
void init_flag_defaults()
initialize all format flags to their default value
Definition: OStream.cpp:101
NoUnderline nounderline
Definition: OStream.cpp:65
FloatFormat float_fmt
format used to print floating point types
Definition: OStream.hpp:295
OStream & operator<<(char)
Definition: OStream.cpp:209
Underline underline
Definition: OStream.cpp:64
size_t width
padding for next write
Definition: OStream.hpp:258
static SetPrefix setprefix(const char *prefix, Color color)
Definition: OStream.hpp:407
void init_persistent_flags()
initialize all flags that survive a write operation
Definition: OStream.cpp:114
Hex hex
Definition: OStream.cpp:50
FillZero fillzero
Definition: OStream.cpp:45
int precision
precision
Definition: OStream.hpp:266
SetWidth(size_t width)
Definition: OStream.hpp:329
Right right
Definition: OStream.cpp:47
bool newline
true iff we are at the beginning of a new line
Definition: OStream.hpp:228
OStream(FILE *file)
create a new stream with default flags
Definition: OStream.cpp:67
Bold bold
Definition: OStream.cpp:62
Indent indent
Definition: OStream.cpp:54
enum cacao::OStream::@2 align
Alignment to use when padding text.
static SetPrecision setprecision(int p)
Definition: OStream.hpp:401
void on_newline()
Definition: OStream.cpp:125
Set indent level in stream.
Definition: OStream.hpp:353
SetIndent(size_t indent)
Definition: OStream.hpp:356
Left left
Definition: OStream.cpp:46
Color prefix_color
color line prefix is printed in
Definition: OStream.hpp:320
static void set_force_color(int)
force color (0 = disabled, 1 = yes, 0 = no)
Definition: OStream.cpp:76
static int force_color
force color (0 = disabled, 1 = yes, 0 = no)
Definition: OStream.hpp:237
const char * prefix
line prefix
Definition: OStream.hpp:312
Simple stream class for formatted output.
Definition: OStream.hpp:141
ThreadId threadid
Definition: OStream.cpp:59
SetPrefix(const char *prefix, Color color)
Definition: OStream.hpp:366
MIIterator i
ResetColor reset_color
Definition: OStream.cpp:61
OStream & OS
Flush flush
Definition: OStream.cpp:57
OStream & operator<<(OStream &OS, const std::string &t)
Definition: OStream.hpp:459
OStream & err()
Definition: OStream.cpp:33
bool fill_zero
fill_zero
Definition: OStream.hpp:274
MIIterator e
FloatHex float_hex
Definition: OStream.cpp:53
NoBold nobold
Definition: OStream.cpp:63
void set_file(FILE *file)
Definition: OStream.hpp:209
SetPrecision(int precision)
Definition: OStream.hpp:347
Set width flag for next item to be written.
Definition: OStream.hpp:326
OStream & out()
Definition: OStream.cpp:39
bool use_color() const
supports ansi escape codes
Definition: OStream.cpp:87
friend class Logging
Definition: OStream.hpp:322
const char * prefix
Definition: OStream.hpp:363
Set width flag and fill zero for next item to be written.
Definition: OStream.hpp:335
OStream & print_ptr_container(OStream &OS, _ForwardIterator i, const _ForwardIterator &e)
Definition: OStream.hpp:448
void init_transient_flags()
initialize all flags that only apply to one write operation
Definition: OStream.cpp:106
Dedent dedent
Definition: OStream.cpp:55
static SetIndent setindent(size_t i)
Definition: OStream.hpp:404
Nl nl
Definition: OStream.cpp:56
static SetZero setz(size_t w)
Definition: OStream.hpp:398
Dec dec
Definition: OStream.cpp:48
Scientific scientific
Definition: OStream.cpp:52
Oct oct
Definition: OStream.cpp:49
bool _use_color
supports ansi escape codes
Definition: OStream.hpp:231
FILE * file
file stream writes to
Definition: OStream.hpp:225