LCOV - code coverage report
Current view: top level - toolbox - OStream.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 189 0.0 %
Date: 2015-06-10 18:10:59 Functions: 0 44 0.0 %

          Line data    Source code
       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             : 
      33           0 : OStream& err() {
      34           0 :         static OStream stream(stderr);
      35             : 
      36           0 :         return stream;
      37             : }
      38             : 
      39           0 : OStream& out() {
      40           0 :         static OStream stream(stdout);
      41             : 
      42           0 :         return stream;
      43             : }
      44             : 
      45             : FillZero   fillzero;
      46             : Left       left;
      47             : Right      right;
      48             : Dec        dec;
      49             : Oct        oct;
      50             : Hex        hex;
      51             : FloatDec   float_dec;
      52             : Scientific scientific;
      53             : FloatHex   float_hex;
      54             : Indent     indent;
      55             : Dedent     dedent;
      56             : Nl         nl;
      57             : Flush      flush;
      58             : 
      59             : ThreadId threadid;
      60             : 
      61             : ResetColor  reset_color;
      62             : Bold        bold;
      63             : NoBold      nobold;
      64             : Underline   underline;
      65             : NoUnderline nounderline;
      66             : 
      67           0 : OStream::OStream(FILE *file) : file(file), newline(true) {
      68           0 :         assert(file);
      69           0 :         init_flag_defaults();
      70             :         // in practice all tty's support ansi escape codes
      71           0 :         use_color = isatty(fileno(file));
      72           0 : }
      73             : 
      74           0 : OStream::OStream(const OStream& os) : file(os.file), newline(os.newline), use_color(os.use_color) {
      75           0 :         init_flag_defaults();
      76           0 : }
      77             : 
      78           0 : void OStream::init_flag_defaults() {
      79           0 :         init_transient_flags();
      80           0 :         init_persistent_flags();
      81           0 : }
      82             : 
      83           0 : void OStream::init_transient_flags() {
      84             :         // keep comments in Flags class in sync with this!
      85             : 
      86           0 :         width = 0;
      87           0 :         precision = -1;
      88           0 :         fill_zero = false;
      89           0 : }
      90             : 
      91           0 : void OStream::init_persistent_flags() {
      92             :         // keep comments in Flags class in sync with this!
      93             : 
      94           0 :         align           = Align_right;
      95           0 :         int_fmt         = OStream::IntFmt_decimal;
      96           0 :         float_fmt       = OStream::FloatFmt_decimal;
      97           0 :         indent_lvl      = 0;
      98           0 :         prefix          = NULL;
      99           0 :         prefix_color    = InvalidColor;
     100           0 : }
     101             : 
     102           0 : void OStream::on_newline() {
     103           0 :         if (!newline) return;
     104             : 
     105           0 :         newline = false;
     106             : 
     107             :         // set color
     108             : 
     109           0 :         if (prefix_color != InvalidColor) (*this) << prefix_color;
     110             : 
     111             :         // print prefix
     112             : 
     113           0 :         if (prefix) {
     114           0 :                 fputs(prefix, file);
     115           0 :                 fputc(' ', file);
     116             :         }
     117             : 
     118             :         // reset color
     119             : 
     120           0 :         if (prefix_color != InvalidColor) (*this) << reset_color;
     121             : 
     122             :         // indent
     123             : 
     124           0 :         for (size_t indent = indent_lvl * 4; indent > 0; indent--) {
     125           0 :                 fputc(' ', file);
     126             :         }
     127             : }
     128             : 
     129             : #define PRINT_INT_FLAG(DEC, OCT, HEX, VAL, FLAG)                                        \
     130             :         switch (int_fmt) {                                                                  \
     131             :                 case IntFmt_decimal:                                                            \
     132             :                         fprintf(file, "%" FLAG "*" #DEC, (int) width, VAL);break;                   \
     133             :                 case IntFmt_octal:                                                              \
     134             :                         fprintf(file, "%" FLAG "*" #OCT, (int) width, VAL);break;                   \
     135             :                 case IntFmt_hexadecimal:                                                        \
     136             :                         fprintf(file, "%" FLAG "*" #HEX, (int) width, VAL);break;                   \
     137             :                 default:                 assert(false && "Bad int format");                     \
     138             :         }
     139             : 
     140             : #define PRINT_INT(DEC, OCT, HEX, VAL)                                                   \
     141             :         switch (align) {                                                                    \
     142             :         case Align_left:                                                                    \
     143             :                 /* left align (i.e. - ) and zero padding not valid */                           \
     144             :                 PRINT_INT_FLAG(DEC,OCT,HEX,VAL,"-");                                            \
     145             :                 break;                                                                          \
     146             :         case Align_right:                                                                   \
     147             :                 if (fill_zero) {                                                                \
     148             :                         PRINT_INT_FLAG(DEC,OCT,HEX,VAL,"0");                                        \
     149             :                 } else {                                                                        \
     150             :                         PRINT_INT_FLAG(DEC,OCT,HEX,VAL,"");                                         \
     151             :                 }                                                                               \
     152             :                 break;                                                                          \
     153             :         default:                                                                            \
     154             :                 assert(false && "Bad alignment");                                               \
     155             :         }
     156             : 
     157             : #define PRINT_FLOAT_FLAG(DEC, SCI, HEX, VAL, FLAG)                                      \
     158             :         switch (float_fmt) {                                                                \
     159             :                 case FloatFmt_decimal:                                                          \
     160             :                         fprintf(file, "%" FLAG "*.*" #DEC, (int) width, precision, VAL); break;     \
     161             :                 case FloatFmt_scientific:                                                       \
     162             :                         fprintf(file, "%" FLAG "*.*" #SCI, (int) width, precision, VAL); break;     \
     163             :                 case FloatFmt_hexadecimal:                                                      \
     164             :                         fprintf(file, "%" FLAG "*.*" #HEX, (int) width, precision, VAL); break;     \
     165             :                 default:                                                                        \
     166             :                         assert(false && "Bad float format");                                        \
     167             :         }
     168             : 
     169             : #define PRINT_FLOAT(DEC, SCI, HEX, VAL)                                                 \
     170             :         switch (align) {                                                                    \
     171             :         case Align_left:                                                                    \
     172             :                 /* left align (i.e. - ) and zero padding not valid */                           \
     173             :                 PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,"-");                                          \
     174             :                 break;                                                                          \
     175             :         case Align_right:                                                                   \
     176             :                 if (fill_zero) {                                                                \
     177             :                         PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,"0");                                      \
     178             :                 } else {                                                                        \
     179             :                         PRINT_FLOAT_FLAG(DEC,SCI,HEX,VAL,"");                                       \
     180             :                 }                                                                               \
     181             :                 break;                                                                          \
     182             :         default:                                                                            \
     183             :                 assert(false && "Bad alignment");                                               \
     184             :         }
     185             : 
     186           0 : OStream& OStream::operator<<(char c) {
     187           0 :         on_newline();
     188             : 
     189           0 :         if (!width) {
     190           0 :                 fputc(c, file);
     191             :         } else {
     192           0 :                 switch (align) {
     193             :                 case Align_left:
     194           0 :                         fprintf(file, "%-*c", (int) width, c);
     195           0 :                         break;
     196             :                 case Align_right:
     197           0 :                         fprintf(file, "%*c", (int) width, c);
     198             :                         break;
     199             :                 }
     200             :         }
     201             : 
     202           0 :         init_transient_flags();
     203           0 :         return (*this);
     204             : }
     205           0 : OStream& OStream::operator<<(bool b) {
     206           0 :         return (*this) << (b ? "true" : "false");
     207             : }
     208           0 : OStream& OStream::operator<<(long n) {
     209           0 :         on_newline();
     210             : 
     211           0 :         PRINT_INT(ld, lo, lx, n);
     212             : 
     213           0 :         init_transient_flags();
     214           0 :         return (*this);
     215             : }
     216           0 : OStream& OStream::operator<<(long long n) {
     217           0 :         on_newline();
     218             : 
     219           0 :         PRINT_INT(lld, llo, llx, n);
     220             : 
     221           0 :         init_transient_flags();
     222           0 :         return (*this);
     223             : }
     224           0 : OStream& OStream::operator<<(unsigned long n) {
     225           0 :         on_newline();
     226             : 
     227           0 :         PRINT_INT(lu, lo, lx, n);
     228             : 
     229           0 :         init_transient_flags();
     230           0 :         return (*this);
     231             : }
     232           0 : OStream& OStream::operator<<(unsigned long long n) {
     233           0 :         on_newline();
     234             : 
     235           0 :         PRINT_INT(llu, llo, llx, n);
     236             : 
     237           0 :         init_transient_flags();
     238           0 :         return (*this);
     239             : }
     240             : /**
     241             :  * @Cpp11 Flag %a introduced in C99, disable hex float for now
     242             :  */
     243           0 : OStream& OStream::operator<<(double n) {
     244           0 :         on_newline();
     245             : 
     246             :         //PRINT_FLOAT(f, e, a, n);
     247           0 :         PRINT_FLOAT(f, e, e, n);
     248             : 
     249           0 :         init_transient_flags();
     250           0 :         return (*this);
     251             : }
     252           0 : OStream& OStream::operator<<(const void *p) {
     253           0 :         on_newline();
     254             : 
     255           0 :         if (!p) return (*this) << "NULL";
     256             : 
     257           0 :         OStream OS = (*this); // new OStream for new flags
     258           0 :         OS << "0x" << hex << (const long int)p;
     259           0 :         return (*this);
     260             : }
     261           0 : OStream& OStream::operator<<(const char *cs) {
     262           0 :         on_newline();
     263             : 
     264           0 :         if (!cs) cs = "(null)";
     265             : 
     266           0 :         if (!width) {
     267           0 :                 fputs(cs, file);
     268             :         } else {
     269           0 :                 switch (align) {
     270             :                 case Align_left:
     271           0 :                         fprintf(file, "%-*s", (int) width, cs);
     272           0 :                         break;
     273             :                 case Align_right:
     274           0 :                         fprintf(file, "%*s", (int) width, cs);
     275             :                         break;
     276             :                 }
     277             :         }
     278             : 
     279           0 :         init_transient_flags();
     280           0 :         return (*this);
     281             : }
     282             : 
     283           0 : OStream& OStream::operator<<(const SetWidth& s) {
     284           0 :         width = s.width;
     285             : 
     286           0 :         return (*this);
     287             : }
     288           0 : OStream& OStream::operator<<(const SetZero& s) {
     289           0 :         width = s.width;
     290           0 :         fill_zero = true;
     291           0 :         return (*this);
     292             : }
     293           0 : OStream& OStream::operator<<(const SetPrecision& s) {
     294           0 :         precision = s.precision;
     295             : 
     296           0 :         return (*this);
     297             : }
     298           0 : OStream& OStream::operator<<(const SetIndent& s) {
     299           0 :         indent_lvl = s.indent;
     300             : 
     301           0 :         return (*this);
     302             : }
     303           0 : OStream& OStream::operator<<(const SetPrefix& s) {
     304           0 :         prefix       = s.prefix;
     305           0 :         prefix_color = s.color;
     306             : 
     307           0 :         return (*this);
     308             : }
     309             : 
     310           0 : OStream& OStream::operator<<(const FillZero&) {
     311           0 :         fill_zero = true;
     312             : 
     313           0 :         return (*this);
     314             : }
     315             : 
     316           0 : OStream& OStream::operator<<(const Left&) {
     317           0 :         align = OStream::Align_left;
     318             : 
     319           0 :         return (*this);
     320             : }
     321           0 : OStream& OStream::operator<<(const Right&) {
     322           0 :         align = OStream::Align_right;
     323             : 
     324           0 :         return (*this);
     325             : }
     326           0 : OStream& OStream::operator<<(const Dec&) {
     327           0 :         int_fmt = OStream::IntFmt_decimal;
     328             : 
     329           0 :         return (*this);
     330             : }
     331           0 : OStream& OStream::operator<<(const Oct&) {
     332           0 :         int_fmt = OStream::IntFmt_octal;
     333             : 
     334           0 :         return (*this);
     335             : }
     336           0 : OStream& OStream::operator<<(const Hex&) {
     337           0 :         int_fmt = OStream::IntFmt_hexadecimal;
     338             : 
     339           0 :         return (*this);
     340             : }
     341           0 : OStream& OStream::operator<<(const FloatDec&) {
     342           0 :         float_fmt = OStream::FloatFmt_decimal;
     343             : 
     344           0 :         return (*this);
     345             : }
     346           0 : OStream& OStream::operator<<(const Scientific&) {
     347           0 :         float_fmt = OStream::FloatFmt_scientific;
     348             : 
     349           0 :         return (*this);
     350             : }
     351           0 : OStream& OStream::operator<<(const FloatHex&) {
     352           0 :         float_fmt = OStream::FloatFmt_hexadecimal;
     353             : 
     354           0 :         return (*this);
     355             : }
     356           0 : OStream& OStream::operator<<(const Indent&) {
     357           0 :         indent_lvl++;
     358             : 
     359           0 :         return (*this);
     360             : }
     361           0 : OStream& OStream::operator<<(const Dedent&) {
     362           0 :         indent_lvl--;
     363             : 
     364           0 :         return (*this);
     365             : }
     366           0 : OStream& OStream::operator<<(const Nl&) {
     367           0 :         (*this) << '\n';
     368           0 :         newline = true;
     369             : 
     370           0 :         return (*this);
     371             : }
     372           0 : OStream& OStream::operator<<(const Flush&) {
     373           0 :         fflush(file);
     374             : 
     375           0 :         return (*this);
     376             : }
     377             : 
     378           0 : OStream& OStream::operator<<(const ThreadId&) {
     379           0 :         return (*this) << "[" << hex << setw(16) << fillzero << threads_get_current_tid() << dec << "]";
     380             : }
     381             : 
     382           0 : OStream& OStream::operator<<(Color c) {
     383           0 :         if (!use_color) return (*this);
     384             : 
     385           0 :         switch (c) {
     386           0 :         case Black:       return (*this) << "\033[30m";
     387           0 :         case Red:         return (*this) << "\033[31m";
     388           0 :         case Green:       return (*this) << "\033[32m";
     389           0 :         case Yellow:      return (*this) << "\033[33m";
     390           0 :         case Blue:        return (*this) << "\033[34m";
     391           0 :         case Magenta:     return (*this) << "\033[35m";
     392           0 :         case Cyan:        return (*this) << "\033[36m";
     393           0 :         case White:       return (*this) << "\033[37m";
     394           0 :         case BoldBlack:   return (*this) << "\033[30m\033[1m";
     395           0 :         case BoldRed:     return (*this) << "\033[31m\033[1m";
     396           0 :         case BoldGreen:   return (*this) << "\033[32m\033[1m";
     397           0 :         case BoldYellow:  return (*this) << "\033[33m\033[1m";
     398           0 :         case BoldBlue:    return (*this) << "\033[34m\033[1m";
     399           0 :         case BoldMagenta: return (*this) << "\033[35m\033[1m";
     400           0 :         case BoldCyan:    return (*this) << "\033[36m\033[1m";
     401           0 :         case BoldWhite:   return (*this) << "\033[37m\033[1m";
     402             :         default:
     403           0 :                 assert(false && "Unknown color code");
     404             :                 break;
     405             :         }
     406             : 
     407             :         return (*this);
     408             : }
     409           0 : OStream& OStream::operator<<(const ResetColor&) {
     410           0 :         if (!use_color) return (*this);
     411           0 :         return (*this) << "\033[0m";
     412             : }
     413           0 : OStream& OStream::operator<<(const Bold&) {
     414           0 :         if (!use_color) return (*this);
     415           0 :         return (*this) << "\033[1m";
     416             : }
     417           0 : OStream& OStream::operator<<(const NoBold&) {
     418           0 :         if (!use_color) return (*this);
     419           0 :         return (*this) << "\033[21m";
     420             : }
     421           0 : OStream& OStream::operator<<(const Underline&) {
     422           0 :         if (!use_color) return (*this);
     423           0 :         return (*this) << "\033[4m";
     424             : }
     425           0 : OStream& OStream::operator<<(const NoUnderline&) {
     426           0 :         if (!use_color) return (*this);
     427           0 :         return (*this) << "\033[24m";
     428             : }
     429             : 
     430             : } // end namespace cacao
     431             : 
     432             : /*
     433             :  * These are local overrides for various environment variables in Emacs.
     434             :  * Please do not remove this and leave it at the end of the file, where
     435             :  * Emacs will automagically detect them.
     436             :  * ---------------------------------------------------------------------
     437             :  * Local variables:
     438             :  * mode: c++
     439             :  * indent-tabs-mode: t
     440             :  * c-basic-offset: 4
     441             :  * tab-width: 4
     442             :  * End:
     443             :  * vim:noexpandtab:sw=4:ts=4:
     444             :  */

Generated by: LCOV version 1.11