brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · abc7149 Raw
201 lines · plain
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 at6//7//     http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// 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 and13// limitations under the License.14 15#include "colorprint.h"16 17#include <cstdarg>18#include <cstdio>19#include <cstdlib>20#include <cstring>21#include <memory>22#include <string>23 24#include "check.h"25#include "internal_macros.h"26 27#ifdef BENCHMARK_OS_WINDOWS28#include <io.h>29#include <windows.h>30#else31#include <unistd.h>32#endif  // BENCHMARK_OS_WINDOWS33 34namespace benchmark {35namespace {36#ifdef BENCHMARK_OS_WINDOWS37typedef WORD PlatformColorCode;38#else39typedef const char* PlatformColorCode;40#endif41 42PlatformColorCode GetPlatformColorCode(LogColor color) {43#ifdef BENCHMARK_OS_WINDOWS44  switch (color) {45    case COLOR_RED:46      return FOREGROUND_RED;47    case COLOR_GREEN:48      return FOREGROUND_GREEN;49    case COLOR_YELLOW:50      return FOREGROUND_RED | FOREGROUND_GREEN;51    case COLOR_BLUE:52      return FOREGROUND_BLUE;53    case COLOR_MAGENTA:54      return FOREGROUND_BLUE | FOREGROUND_RED;55    case COLOR_CYAN:56      return FOREGROUND_BLUE | FOREGROUND_GREEN;57    case COLOR_WHITE:  // fall through to default58    default:59      return 0;60  }61#else62  switch (color) {63    case COLOR_RED:64      return "1";65    case COLOR_GREEN:66      return "2";67    case COLOR_YELLOW:68      return "3";69    case COLOR_BLUE:70      return "4";71    case COLOR_MAGENTA:72      return "5";73    case COLOR_CYAN:74      return "6";75    case COLOR_WHITE:76      return "7";77    default:78      return nullptr;79  };80#endif81}82 83}  // end namespace84 85std::string FormatString(const char* msg, va_list args) {86  // we might need a second shot at this, so pre-emptivly make a copy87  va_list args_cp;88  va_copy(args_cp, args);89 90  std::size_t size = 256;91  char local_buff[256];92  auto ret = vsnprintf(local_buff, size, msg, args_cp);93 94  va_end(args_cp);95 96  // currently there is no error handling for failure, so this is hack.97  BM_CHECK(ret >= 0);98 99  if (ret == 0) {  // handle empty expansion100    return {};101  }102  if (static_cast<size_t>(ret) < size) {103    return local_buff;104  }105  // we did not provide a long enough buffer on our first attempt.106  size = static_cast<size_t>(ret) + 1;  // + 1 for the null byte107  std::unique_ptr<char[]> buff(new char[size]);108  ret = vsnprintf(buff.get(), size, msg, args);109  BM_CHECK(ret > 0 && (static_cast<size_t>(ret)) < size);110  return buff.get();111}112 113std::string FormatString(const char* msg, ...) {114  va_list args;115  va_start(args, msg);116  auto tmp = FormatString(msg, args);117  va_end(args);118  return tmp;119}120 121void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {122  va_list args;123  va_start(args, fmt);124  ColorPrintf(out, color, fmt, args);125  va_end(args);126}127 128void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,129                 va_list args) {130#ifdef BENCHMARK_OS_WINDOWS131  ((void)out);  // suppress unused warning132 133  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);134 135  // Gets the current text color.136  CONSOLE_SCREEN_BUFFER_INFO buffer_info;137  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);138  const WORD old_color_attrs = buffer_info.wAttributes;139 140  // We need to flush the stream buffers into the console before each141  // SetConsoleTextAttribute call lest it affect the text that is already142  // printed but has not yet reached the console.143  out.flush();144  SetConsoleTextAttribute(stdout_handle,145                          GetPlatformColorCode(color) | FOREGROUND_INTENSITY);146  out << FormatString(fmt, args);147 148  out.flush();149  // Restores the text color.150  SetConsoleTextAttribute(stdout_handle, old_color_attrs);151#else152  const char* color_code = GetPlatformColorCode(color);153  if (color_code) out << FormatString("\033[0;3%sm", color_code);154  out << FormatString(fmt, args) << "\033[m";155#endif156}157 158bool IsColorTerminal() {159#if BENCHMARK_OS_WINDOWS160  // On Windows the TERM variable is usually not set, but the161  // console there does support colors.162  return 0 != _isatty(_fileno(stdout));163#else164  // On non-Windows platforms, we rely on the TERM variable. This list of165  // supported TERM values is copied from Google Test:166  // <https://github.com/google/googletest/blob/v1.13.0/googletest/src/gtest.cc#L3225-L3259>.167  const char* const SUPPORTED_TERM_VALUES[] = {168      "xterm",169      "xterm-color",170      "xterm-256color",171      "screen",172      "screen-256color",173      "tmux",174      "tmux-256color",175      "rxvt-unicode",176      "rxvt-unicode-256color",177      "linux",178      "cygwin",179      "xterm-kitty",180      "alacritty",181      "foot",182      "foot-extra",183      "wezterm",184  };185 186  const char* const term = getenv("TERM");187 188  bool term_supports_color = false;189  for (const char* candidate : SUPPORTED_TERM_VALUES) {190    if (term && 0 == strcmp(term, candidate)) {191      term_supports_color = true;192      break;193    }194  }195 196  return 0 != isatty(fileno(stdout)) && term_supports_color;197#endif  // BENCHMARK_OS_WINDOWS198}199 200}  // end namespace benchmark201