Home | History | Annotate | Download | only in src
      1 // Copyright 2015 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "colorprint.h"
     16 
     17 #include <cstdarg>
     18 #include <cstdio>
     19 
     20 #include "commandlineflags.h"
     21 #include "internal_macros.h"
     22 
     23 #ifdef BENCHMARK_OS_WINDOWS
     24 #include <Windows.h>
     25 #endif
     26 
     27 DECLARE_bool(color_print);
     28 
     29 namespace benchmark {
     30 namespace {
     31 #ifdef BENCHMARK_OS_WINDOWS
     32 typedef WORD PlatformColorCode;
     33 #else
     34 typedef const char* PlatformColorCode;
     35 #endif
     36 
     37 PlatformColorCode GetPlatformColorCode(LogColor color) {
     38 #ifdef BENCHMARK_OS_WINDOWS
     39   switch (color) {
     40     case COLOR_RED:
     41       return FOREGROUND_RED;
     42     case COLOR_GREEN:
     43       return FOREGROUND_GREEN;
     44     case COLOR_YELLOW:
     45       return FOREGROUND_RED | FOREGROUND_GREEN;
     46     case COLOR_BLUE:
     47       return FOREGROUND_BLUE;
     48     case COLOR_MAGENTA:
     49       return FOREGROUND_BLUE | FOREGROUND_RED;
     50     case COLOR_CYAN:
     51       return FOREGROUND_BLUE | FOREGROUND_GREEN;
     52     case COLOR_WHITE:  // fall through to default
     53     default:
     54       return 0;
     55   }
     56 #else
     57   switch (color) {
     58     case COLOR_RED:
     59       return "1";
     60     case COLOR_GREEN:
     61       return "2";
     62     case COLOR_YELLOW:
     63       return "3";
     64     case COLOR_BLUE:
     65       return "4";
     66     case COLOR_MAGENTA:
     67       return "5";
     68     case COLOR_CYAN:
     69       return "6";
     70     case COLOR_WHITE:
     71       return "7";
     72     default:
     73       return nullptr;
     74   };
     75 #endif
     76 }
     77 }  // end namespace
     78 
     79 void ColorPrintf(LogColor color, const char* fmt, ...) {
     80   va_list args;
     81   va_start(args, fmt);
     82 
     83   if (!FLAGS_color_print) {
     84     vprintf(fmt, args);
     85     va_end(args);
     86     return;
     87   }
     88 
     89 #ifdef BENCHMARK_OS_WINDOWS
     90   const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
     91 
     92   // Gets the current text color.
     93   CONSOLE_SCREEN_BUFFER_INFO buffer_info;
     94   GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
     95   const WORD old_color_attrs = buffer_info.wAttributes;
     96 
     97   // We need to flush the stream buffers into the console before each
     98   // SetConsoleTextAttribute call lest it affect the text that is already
     99   // printed but has not yet reached the console.
    100   fflush(stdout);
    101   SetConsoleTextAttribute(stdout_handle,
    102                           GetPlatformColorCode(color) | FOREGROUND_INTENSITY);
    103   vprintf(fmt, args);
    104 
    105   fflush(stdout);
    106   // Restores the text color.
    107   SetConsoleTextAttribute(stdout_handle, old_color_attrs);
    108 #else
    109   const char* color_code = GetPlatformColorCode(color);
    110   if (color_code) fprintf(stdout, "\033[0;3%sm", color_code);
    111   vprintf(fmt, args);
    112   printf("\033[m");  // Resets the terminal to default.
    113 #endif
    114   va_end(args);
    115 }
    116 }  // end namespace benchmark
    117