CACAO
OStream.cpp
Go to the documentation of this file.
1 /* src/toolbox/OStream.cpp - 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 #include "toolbox/OStream.hpp"
26 
27 #include "threads/thread.hpp"
28 
29 #include <cassert>
30 
31 namespace cacao {
32 
34  static OStream stream(stderr);
35 
36  return stream;
37 }
38 
40  static OStream stream(stdout);
41 
42  return stream;
43 }
44 
58 
60 
66 
67 OStream::OStream(FILE *file) : file(file), newline(true) {
68  assert(file);
70  // in practice all tty's support ansi escape codes
71  _use_color = isatty(fileno(file));
72 }
73 
74 int OStream::force_color = 0;
75 
77  switch(b){
78  case 1:
79  case -1:
80  force_color = b;
81  break;
82  default:
83  force_color = 0;
84  }
85 }
86 
87 inline bool OStream::use_color() const {
88  switch (force_color) {
89  case 1:
90  return true;
91  case -1:
92  return false;
93  }
94  return _use_color;
95 }
96 
97 OStream::OStream(const OStream& os) : file(os.file), newline(os.newline), _use_color(os._use_color) {
99 }
100 
104 }
105 
107  // keep comments in Flags class in sync with this!
108 
109  width = 0;
110  precision = -1;
111  fill_zero = false;
112 }
113 
115  // keep comments in Flags class in sync with this!
116 
117  align = Align_right;
120  indent_lvl = 0;
121  prefix = NULL;
123 }
124 
126  if (!newline) return;
127 
128  newline = false;
129 
130  // set color
131 
132  if (prefix_color != InvalidColor) (*this) << prefix_color;
133 
134  // print prefix
135 
136  if (prefix) {
137  fputs(prefix, file);
138  fputc(' ', file);
139  }
140 
141  // reset color
142 
143  if (prefix_color != InvalidColor) (*this) << reset_color;
144 
145  // indent
146 
147  for (size_t indent = indent_lvl * 4; indent > 0; indent--) {
148  fputc(' ', file);
149  }
150 }
151 
152 #define PRINT_INT_FLAG(DEC, OCT, HEX, VAL, FLAG) \
153  switch (int_fmt) { \
154  case IntFmt_decimal: \
155  fprintf(file, "%" FLAG "*" #DEC, (int) width, VAL);break; \
156  case IntFmt_octal: \
157  fprintf(file, "%" FLAG "*" #OCT, (int) width, VAL);break; \
158  case IntFmt_hexadecimal: \
159  fprintf(file, "%" FLAG "*" #HEX, (int) width, VAL);break; \
160  default: assert(false && "Bad int format"); \
161  }
162 
163 #define PRINT_INT(DEC, OCT, HEX, VAL) \
164  switch (align) { \
165  case Align_left: \
166  /* left align (i.e. - ) and zero padding not valid */ \
167  PRINT_INT_FLAG(DEC,OCT,HEX,VAL,"-"); \
168  break; \
169  case Align_right: \
170  if (fill_zero) { \
171  PRINT_INT_FLAG(DEC,OCT,HEX,VAL,"0"); \
172  } else { \
173  PRINT_INT_FLAG(DEC,OCT,HEX,VAL,""); \
174  } \
175  break; \
176  default: \
177  assert(false && "Bad alignment"); \
178  }
179 
180 #define PRINT_FLOAT_FLAG(DEC, SCI, HEX, VAL, FLAG) \
181  switch (float_fmt) { \
182  case FloatFmt_decimal: \
183  fprintf(file, "%" FLAG "*.*" #DEC, (int) width, precision, VAL); break; \
184  case FloatFmt_scientific: \
185  fprintf(file, "%" FLAG "*.*" #SCI, (int) width, precision, VAL); break; \
186  case FloatFmt_hexadecimal: \
187  fprintf(file, "%" FLAG "*.*" #HEX, (int) width, precision, VAL); break; \
188  default: \
189  assert(false && "Bad float format"); \
190  }
191 
192 #define PRINT_FLOAT(DEC, SCI, HEX, VAL) \
193  switch (align) { \
194  case Align_left: \
195  /* left align (i.e. - ) and zero padding not valid */ \
196  PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,"-"); \
197  break; \
198  case Align_right: \
199  if (fill_zero) { \
200  PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,"0"); \
201  } else { \
202  PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,""); \
203  } \
204  break; \
205  default: \
206  assert(false && "Bad alignment"); \
207  }
208 
210  on_newline();
211 
212  if (!width) {
213  fputc(c, file);
214  } else {
215  switch (align) {
216  case Align_left:
217  fprintf(file, "%-*c", (int) width, c);
218  break;
219  case Align_right:
220  fprintf(file, "%*c", (int) width, c);
221  break;
222  }
223  }
224 
226  return (*this);
227 }
229  return (*this) << (b ? "true" : "false");
230 }
232  on_newline();
233 
234  PRINT_INT(ld, lo, lx, n);
235 
237  return (*this);
238 }
240  on_newline();
241 
242  PRINT_INT(lld, llo, llx, n);
243 
245  return (*this);
246 }
247 OStream& OStream::operator<<(unsigned long n) {
248  on_newline();
249 
250  PRINT_INT(lu, lo, lx, n);
251 
253  return (*this);
254 }
255 OStream& OStream::operator<<(unsigned long long n) {
256  on_newline();
257 
258  PRINT_INT(llu, llo, llx, n);
259 
261  return (*this);
262 }
263 /**
264  * @Cpp11 Flag %a introduced in C99, disable hex float for now
265  */
267  on_newline();
268 
269  //PRINT_FLOAT(f, e, a, n);
270  PRINT_FLOAT(f, e, e, n);
271 
273  return (*this);
274 }
275 OStream& OStream::operator<<(const void *p) {
276  on_newline();
277 
278  if (!p) return (*this) << "NULL";
279 
280  OStream OS = (*this); // new OStream for new flags
281  OS << "0x" << hex << (const long int)p;
282  return (*this);
283 }
284 OStream& OStream::operator<<(const char *cs) {
285  on_newline();
286 
287  if (!cs) cs = "(null)";
288 
289  if (!width) {
290  fputs(cs, file);
291  } else {
292  switch (align) {
293  case Align_left:
294  fprintf(file, "%-*s", (int) width, cs);
295  break;
296  case Align_right:
297  fprintf(file, "%*s", (int) width, cs);
298  break;
299  }
300  }
301 
303  return (*this);
304 }
305 
307  width = s.width;
308 
309  return (*this);
310 }
312  width = s.width;
313  fill_zero = true;
314  return (*this);
315 }
317  precision = s.precision;
318 
319  return (*this);
320 }
322  indent_lvl = s.indent;
323 
324  return (*this);
325 }
327  prefix = s.prefix;
328  prefix_color = s.color;
329 
330  return (*this);
331 }
332 
334  fill_zero = true;
335 
336  return (*this);
337 }
338 
341 
342  return (*this);
343 }
346 
347  return (*this);
348 }
351 
352  return (*this);
353 }
356 
357  return (*this);
358 }
361 
362  return (*this);
363 }
366 
367  return (*this);
368 }
371 
372  return (*this);
373 }
376 
377  return (*this);
378 }
380  indent_lvl++;
381 
382  return (*this);
383 }
385  indent_lvl--;
386 
387  return (*this);
388 }
390  (*this) << '\n';
391  newline = true;
392 
393  return (*this);
394 }
396  fflush(file);
397 
398  return (*this);
399 }
400 
402  return (*this) << "[" << hex << setw(16) << fillzero << threads_get_current_tid() << dec << "]";
403 }
404 
406  if (!use_color()) return (*this);
407 
408  switch (c) {
409  case Black: return (*this) << "\033[30m";
410  case Red: return (*this) << "\033[31m";
411  case Green: return (*this) << "\033[32m";
412  case Yellow: return (*this) << "\033[33m";
413  case Blue: return (*this) << "\033[34m";
414  case Magenta: return (*this) << "\033[35m";
415  case Cyan: return (*this) << "\033[36m";
416  case White: return (*this) << "\033[37m";
417  case BoldBlack: return (*this) << "\033[30m\033[1m";
418  case BoldRed: return (*this) << "\033[31m\033[1m";
419  case BoldGreen: return (*this) << "\033[32m\033[1m";
420  case BoldYellow: return (*this) << "\033[33m\033[1m";
421  case BoldBlue: return (*this) << "\033[34m\033[1m";
422  case BoldMagenta: return (*this) << "\033[35m\033[1m";
423  case BoldCyan: return (*this) << "\033[36m\033[1m";
424  case BoldWhite: return (*this) << "\033[37m\033[1m";
425  default:
426  assert(false && "Unknown color code");
427  break;
428  }
429 
430  return (*this);
431 }
433  if (!use_color()) return (*this);
434  return (*this) << "\033[0m";
435 }
437  if (!use_color()) return (*this);
438  return (*this) << "\033[1m";
439 }
441  if (!use_color()) return (*this);
442  return (*this) << "\033[21m";
443 }
445  if (!use_color()) return (*this);
446  return (*this) << "\033[4m";
447 }
449  if (!use_color()) return (*this);
450  return (*this) << "\033[24m";
451 }
452 
453 } // end namespace cacao
454 
455 /*
456  * These are local overrides for various environment variables in Emacs.
457  * Please do not remove this and leave it at the end of the file, where
458  * Emacs will automagically detect them.
459  * ---------------------------------------------------------------------
460  * Local variables:
461  * mode: c++
462  * indent-tabs-mode: t
463  * c-basic-offset: 4
464  * tab-width: 4
465  * End:
466  * vim:noexpandtab:sw=4:ts=4:
467  */
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
Definition: os.hpp:123
IntegerFormat int_fmt
format used to print integer types
Definition: OStream.hpp:289
size_t width
Definition: OStream.hpp:336
Set precision flag for next item to be written.
Definition: OStream.hpp:344
Set stream prefix.
Definition: OStream.hpp:362
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
return true
Definition: PatcherNew.cpp:104
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
#define PRINT_FLOAT(DEC, SCI, HEX, VAL)
Definition: OStream.cpp:192
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
#define PRINT_INT(DEC, OCT, HEX, VAL)
Definition: OStream.cpp:163
enum cacao::OStream::@2 align
Alignment to use when padding text.
void on_newline()
Definition: OStream.cpp:125
Set indent level in stream.
Definition: OStream.hpp:353
Left left
Definition: OStream.cpp:46
intptr_t threads_get_current_tid(void)
Definition: thread.cpp:722
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
ResetColor reset_color
Definition: OStream.cpp:61
OStream & OS
Flush flush
Definition: OStream.cpp:57
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
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
const char * prefix
Definition: OStream.hpp:363
Set width flag and fill zero for next item to be written.
Definition: OStream.hpp:335
void init_transient_flags()
initialize all flags that only apply to one write operation
Definition: OStream.cpp:106
Dedent dedent
Definition: OStream.cpp:55
Nl nl
Definition: OStream.cpp:56
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