LCOV - code coverage report
Current view: top level - toolbox - OStream.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 200 0.0 %
Date: 2017-07-14 10:03:36 Functions: 0 46 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             : int OStream::force_color = 0;
      75             : 
      76           0 : void OStream::set_force_color(int b) {
      77           0 :         switch(b){
      78             :         case 1:
      79             :         case -1:
      80           0 :                 force_color = b;
      81           0 :                 break;
      82             :         default:
      83           0 :                 force_color = 0;
      84             :         }
      85           0 : }
      86             : 
      87           0 : inline bool OStream::use_color() const {
      88           0 :         switch (force_color) {
      89             :         case 1:
      90           0 :                 return true;
      91             :         case -1:
      92           0 :                 return false;
      93             :         }
      94           0 :         return _use_color;
      95             : }
      96             : 
      97           0 : OStream::OStream(const OStream& os) : file(os.file), newline(os.newline), _use_color(os._use_color) {
      98           0 :         init_flag_defaults();
      99           0 : }
     100             : 
     101           0 : void OStream::init_flag_defaults() {
     102           0 :         init_transient_flags();
     103           0 :         init_persistent_flags();
     104           0 : }
     105             : 
     106           0 : void OStream::init_transient_flags() {
     107             :         // keep comments in Flags class in sync with this!
     108             : 
     109           0 :         width = 0;
     110           0 :         precision = -1;
     111           0 :         fill_zero = false;
     112           0 : }
     113             : 
     114           0 : void OStream::init_persistent_flags() {
     115             :         // keep comments in Flags class in sync with this!
     116             : 
     117           0 :         align           = Align_right;
     118           0 :         int_fmt         = OStream::IntFmt_decimal;
     119           0 :         float_fmt       = OStream::FloatFmt_decimal;
     120           0 :         indent_lvl      = 0;
     121           0 :         prefix          = NULL;
     122           0 :         prefix_color    = InvalidColor;
     123           0 : }
     124             : 
     125           0 : void OStream::on_newline() {
     126           0 :         if (!newline) return;
     127             : 
     128           0 :         newline = false;
     129             : 
     130             :         // set color
     131             : 
     132           0 :         if (prefix_color != InvalidColor) (*this) << prefix_color;
     133             : 
     134             :         // print prefix
     135             : 
     136           0 :         if (prefix) {
     137           0 :                 fputs(prefix, file);
     138           0 :                 fputc(' ', file);
     139             :         }
     140             : 
     141             :         // reset color
     142             : 
     143           0 :         if (prefix_color != InvalidColor) (*this) << reset_color;
     144             : 
     145             :         // indent
     146             : 
     147           0 :         for (size_t indent = indent_lvl * 4; indent > 0; indent--) {
     148           0 :                 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             : 
     209           0 : OStream& OStream::operator<<(char c) {
     210           0 :         on_newline();
     211             : 
     212           0 :         if (!width) {
     213           0 :                 fputc(c, file);
     214             :         } else {
     215           0 :                 switch (align) {
     216             :                 case Align_left:
     217           0 :                         fprintf(file, "%-*c", (int) width, c);
     218           0 :                         break;
     219             :                 case Align_right:
     220           0 :                         fprintf(file, "%*c", (int) width, c);
     221             :                         break;
     222             :                 }
     223             :         }
     224             : 
     225           0 :         init_transient_flags();
     226           0 :         return (*this);
     227             : }
     228           0 : OStream& OStream::operator<<(bool b) {
     229           0 :         return (*this) << (b ? "true" : "false");
     230             : }
     231           0 : OStream& OStream::operator<<(long n) {
     232           0 :         on_newline();
     233             : 
     234           0 :         PRINT_INT(ld, lo, lx, n);
     235             : 
     236           0 :         init_transient_flags();
     237           0 :         return (*this);
     238             : }
     239           0 : OStream& OStream::operator<<(long long n) {
     240           0 :         on_newline();
     241             : 
     242           0 :         PRINT_INT(lld, llo, llx, n);
     243             : 
     244           0 :         init_transient_flags();
     245           0 :         return (*this);
     246             : }
     247           0 : OStream& OStream::operator<<(unsigned long n) {
     248           0 :         on_newline();
     249             : 
     250           0 :         PRINT_INT(lu, lo, lx, n);
     251             : 
     252           0 :         init_transient_flags();
     253           0 :         return (*this);
     254             : }
     255           0 : OStream& OStream::operator<<(unsigned long long n) {
     256           0 :         on_newline();
     257             : 
     258           0 :         PRINT_INT(llu, llo, llx, n);
     259             : 
     260           0 :         init_transient_flags();
     261           0 :         return (*this);
     262             : }
     263             : /**
     264             :  * @Cpp11 Flag %a introduced in C99, disable hex float for now
     265             :  */
     266           0 : OStream& OStream::operator<<(double n) {
     267           0 :         on_newline();
     268             : 
     269             :         //PRINT_FLOAT(f, e, a, n);
     270           0 :         PRINT_FLOAT(f, e, e, n);
     271             : 
     272           0 :         init_transient_flags();
     273           0 :         return (*this);
     274             : }
     275           0 : OStream& OStream::operator<<(const void *p) {
     276           0 :         on_newline();
     277             : 
     278           0 :         if (!p) return (*this) << "NULL";
     279             : 
     280           0 :         OStream OS = (*this); // new OStream for new flags
     281           0 :         OS << "0x" << hex << (const long int)p;
     282           0 :         return (*this);
     283             : }
     284           0 : OStream& OStream::operator<<(const char *cs) {
     285           0 :         on_newline();
     286             : 
     287           0 :         if (!cs) cs = "(null)";
     288             : 
     289           0 :         if (!width) {
     290           0 :                 fputs(cs, file);
     291             :         } else {
     292           0 :                 switch (align) {
     293             :                 case Align_left:
     294           0 :                         fprintf(file, "%-*s", (int) width, cs);
     295           0 :                         break;
     296             :                 case Align_right:
     297           0 :                         fprintf(file, "%*s", (int) width, cs);
     298             :                         break;
     299             :                 }
     300             :         }
     301             : 
     302           0 :         init_transient_flags();
     303           0 :         return (*this);
     304             : }
     305             : 
     306           0 : OStream& OStream::operator<<(const SetWidth& s) {
     307           0 :         width = s.width;
     308             : 
     309           0 :         return (*this);
     310             : }
     311           0 : OStream& OStream::operator<<(const SetZero& s) {
     312           0 :         width = s.width;
     313           0 :         fill_zero = true;
     314           0 :         return (*this);
     315             : }
     316           0 : OStream& OStream::operator<<(const SetPrecision& s) {
     317           0 :         precision = s.precision;
     318             : 
     319           0 :         return (*this);
     320             : }
     321           0 : OStream& OStream::operator<<(const SetIndent& s) {
     322           0 :         indent_lvl = s.indent;
     323             : 
     324           0 :         return (*this);
     325             : }
     326           0 : OStream& OStream::operator<<(const SetPrefix& s) {
     327           0 :         prefix       = s.prefix;
     328           0 :         prefix_color = s.color;
     329             : 
     330           0 :         return (*this);
     331             : }
     332             : 
     333           0 : OStream& OStream::operator<<(const FillZero&) {
     334           0 :         fill_zero = true;
     335             : 
     336           0 :         return (*this);
     337             : }
     338             : 
     339           0 : OStream& OStream::operator<<(const Left&) {
     340           0 :         align = OStream::Align_left;
     341             : 
     342           0 :         return (*this);
     343             : }
     344           0 : OStream& OStream::operator<<(const Right&) {
     345           0 :         align = OStream::Align_right;
     346             : 
     347           0 :         return (*this);
     348             : }
     349           0 : OStream& OStream::operator<<(const Dec&) {
     350           0 :         int_fmt = OStream::IntFmt_decimal;
     351             : 
     352           0 :         return (*this);
     353             : }
     354           0 : OStream& OStream::operator<<(const Oct&) {
     355           0 :         int_fmt = OStream::IntFmt_octal;
     356             : 
     357           0 :         return (*this);
     358             : }
     359           0 : OStream& OStream::operator<<(const Hex&) {
     360           0 :         int_fmt = OStream::IntFmt_hexadecimal;
     361             : 
     362           0 :         return (*this);
     363             : }
     364           0 : OStream& OStream::operator<<(const FloatDec&) {
     365           0 :         float_fmt = OStream::FloatFmt_decimal;
     366             : 
     367           0 :         return (*this);
     368             : }
     369           0 : OStream& OStream::operator<<(const Scientific&) {
     370           0 :         float_fmt = OStream::FloatFmt_scientific;
     371             : 
     372           0 :         return (*this);
     373             : }
     374           0 : OStream& OStream::operator<<(const FloatHex&) {
     375           0 :         float_fmt = OStream::FloatFmt_hexadecimal;
     376             : 
     377           0 :         return (*this);
     378             : }
     379           0 : OStream& OStream::operator<<(const Indent&) {
     380           0 :         indent_lvl++;
     381             : 
     382           0 :         return (*this);
     383             : }
     384           0 : OStream& OStream::operator<<(const Dedent&) {
     385           0 :         indent_lvl--;
     386             : 
     387           0 :         return (*this);
     388             : }
     389           0 : OStream& OStream::operator<<(const Nl&) {
     390           0 :         (*this) << '\n';
     391           0 :         newline = true;
     392             : 
     393           0 :         return (*this);
     394             : }
     395           0 : OStream& OStream::operator<<(const Flush&) {
     396           0 :         fflush(file);
     397             : 
     398           0 :         return (*this);
     399             : }
     400             : 
     401           0 : OStream& OStream::operator<<(const ThreadId&) {
     402           0 :         return (*this) << "[" << hex << setw(16) << fillzero << threads_get_current_tid() << dec << "]";
     403             : }
     404             : 
     405           0 : OStream& OStream::operator<<(Color c) {
     406           0 :         if (!use_color()) return (*this);
     407             : 
     408           0 :         switch (c) {
     409           0 :         case Black:       return (*this) << "\033[30m";
     410           0 :         case Red:         return (*this) << "\033[31m";
     411           0 :         case Green:       return (*this) << "\033[32m";
     412           0 :         case Yellow:      return (*this) << "\033[33m";
     413           0 :         case Blue:        return (*this) << "\033[34m";
     414           0 :         case Magenta:     return (*this) << "\033[35m";
     415           0 :         case Cyan:        return (*this) << "\033[36m";
     416           0 :         case White:       return (*this) << "\033[37m";
     417           0 :         case BoldBlack:   return (*this) << "\033[30m\033[1m";
     418           0 :         case BoldRed:     return (*this) << "\033[31m\033[1m";
     419           0 :         case BoldGreen:   return (*this) << "\033[32m\033[1m";
     420           0 :         case BoldYellow:  return (*this) << "\033[33m\033[1m";
     421           0 :         case BoldBlue:    return (*this) << "\033[34m\033[1m";
     422           0 :         case BoldMagenta: return (*this) << "\033[35m\033[1m";
     423           0 :         case BoldCyan:    return (*this) << "\033[36m\033[1m";
     424           0 :         case BoldWhite:   return (*this) << "\033[37m\033[1m";
     425             :         default:
     426           0 :                 assert(false && "Unknown color code");
     427             :                 break;
     428             :         }
     429             : 
     430             :         return (*this);
     431             : }
     432           0 : OStream& OStream::operator<<(const ResetColor&) {
     433           0 :         if (!use_color()) return (*this);
     434           0 :         return (*this) << "\033[0m";
     435             : }
     436           0 : OStream& OStream::operator<<(const Bold&) {
     437           0 :         if (!use_color()) return (*this);
     438           0 :         return (*this) << "\033[1m";
     439             : }
     440           0 : OStream& OStream::operator<<(const NoBold&) {
     441           0 :         if (!use_color()) return (*this);
     442           0 :         return (*this) << "\033[21m";
     443             : }
     444           0 : OStream& OStream::operator<<(const Underline&) {
     445           0 :         if (!use_color()) return (*this);
     446           0 :         return (*this) << "\033[4m";
     447             : }
     448           0 : OStream& OStream::operator<<(const NoUnderline&) {
     449           0 :         if (!use_color()) return (*this);
     450           0 :         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             :  */

Generated by: LCOV version 1.11