blob: 2f656d3239388a295ba3604a3c52e332111aa95d [file] [log] [blame]
// Copyright 2010 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ioutil.h"
#ifndef _WIN32
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#else
# include "config_win.h"
#endif
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include "absl/strings/match.h"
#include "absl/strings/str_split.h"
#include "basictypes.h"
#include "file_dir.h"
#include "filesystem.h"
#include "glog/logging.h"
#include "scoped_fd.h"
using std::string;
namespace {
// Come from Python 2.7 string.whitespace.
static const char* kWhitespaces = "\t\n\x0b\x0c\r ";
} // namespace
namespace devtools_goma {
absl::string_view StringRstrip(absl::string_view str) {
size_t found = str.find_last_not_of(kWhitespaces);
if (found != string::npos)
return str.substr(0, found + 1);
return str.substr(str.size(), 0); // empty string piece.
}
absl::string_view StringStrip(absl::string_view str) {
absl::string_view::size_type found = str.find_last_not_of(kWhitespaces);
if (found == absl::string_view::npos)
return str.substr(str.size(), 0); // empty string piece.
str = str.substr(0, found + 1);
found = str.find_first_not_of(kWhitespaces);
return str.substr(found);
}
void WriteStringToFileOrDie(const string &data, const string &filename,
int permission) {
ScopedFd fd(ScopedFd::Create(filename, permission));
if (!fd.valid()) {
PLOG(FATAL) << "GOMA: failed to open " << filename;
}
if (fd.Write(data.c_str(), data.size()) !=
static_cast<ssize_t>(data.size())) {
PLOG(FATAL) << "GOMA: Cannot write to file " << filename;
}
}
void AppendStringToFileOrDie(const string &data, const string &filename,
int permission) {
ScopedFd fd(ScopedFd::OpenForAppend(filename, permission));
if (!fd.valid()) {
PLOG(FATAL) << "GOMA: failed to open " << filename;
}
if (fd.Write(data.c_str(), data.size()) !=
static_cast<ssize_t>(data.size())) {
PLOG(FATAL) << "GOMA: Cannot write to file " << filename;
}
}
void WriteStdout(absl::string_view data) {
#ifdef _WIN32
HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD bytes_written = 0;
if (!WriteFile(stdout_handle,
data.data(), data.size(),
&bytes_written, nullptr)) {
LOG_SYSRESULT(GetLastError());
}
#else
std::cout << data << std::flush;
#endif
}
void WriteStderr(absl::string_view data) {
#ifdef _WIN32
HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
DWORD bytes_written = 0;
if (!WriteFile(stderr_handle,
data.data(), data.size(),
&bytes_written, nullptr)) {
LOG_SYSRESULT(GetLastError());
}
#else
std::cerr << data;
#endif
}
void FlushLogFiles() {
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
google::FlushLogFiles(google::INFO);
#else
google::FlushLogFiles(google::GLOG_INFO);
#endif
}
string EscapeString(const string& str) {
std::stringstream escaped_str;
escaped_str << "\"";
for (size_t i = 0; i < str.size(); ++i) {
switch (str[i]) {
case '"': escaped_str << "\\\""; break;
case '\\': escaped_str << "\\\\"; break;
case '\b': escaped_str << "\\b"; break;
case '\f': escaped_str << "\\f"; break;
case '\n': escaped_str << "\\n"; break;
case '\r': escaped_str << "\\r"; break;
case '\t': escaped_str << "\\t"; break;
case '\033':
{
// handle escape sequence.
// ESC[1m -> bold
// ESC[0m -> reset
// ESC[0;<bold><fgbg><color>m -> foreground
// <bold> "1;" or ""
// <fgbg> "3" foreground or "4" background
// <color> 0 black / 1 red / 2 green / 4 blue
// For now, just ignore these escape sequence.
size_t next_i = i;
size_t j = i;
if (j + 2 < str.size() && str[j + 1] == '[') {
for (j += 2; j < str.size(); ++j) {
if (str[j] == ';' || (isdigit(str[j])))
continue;
if (str[j] == 'm')
next_i = j;
break;
}
}
if (next_i != i) {
i = next_i;
break;
}
}
FALLTHROUGH_INTENDED;
default:
if (str[i] < 0x20) {
escaped_str << "\\u" << std::hex << std::setw(4)
<< std::setfill('0') << static_cast<int>(str[i]);
} else {
escaped_str << str[i];
}
}
}
escaped_str << "\"";
return escaped_str.str();
}
} // namespace devtools_goma