blob: 3413ddbd36080095dca99b7e3279e133fa08101d [file] [edit]
// Copyright 2023 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "logger.h"
#include "util.h"
namespace {
struct StdioBackend : public Logger::Backend {
StdioBackend(FILE* stream) : stream_(stream) {}
bool Log(StringPiece message) override {
fwrite(message.str_, message.len_, 1, stream_);
fputc('\n', stream_);
return true;
}
bool Log(const char* fmt, va_list args) override {
vfprintf(stream_, fmt, args);
fputc('\n', stream_);
return true;
}
FILE* stream_;
};
struct StdOstreamBackend : public Logger::Backend {
StdOstreamBackend(std::ostream& out) : out_(out) {}
bool Log(StringPiece str) override {
out_.write(str.str_, static_cast<std::streamsize>(str.len_));
out_.put('\n');
return true;
}
std::ostream& out_;
};
struct StringBackend : public Logger::Backend {
StringBackend(std::string& out) : out_(out) {}
bool Log(StringPiece str) override {
out_.append(str.str_, str.len_);
out_.push_back('\n');
return true;
}
bool Log(const char* fmt, va_list args) override {
StringAppendFormat(out_, fmt, args);
out_.push_back('\n');
return true;
}
std::string& out_;
};
struct ProxyBackend : public Logger::Backend {
ProxyBackend(const Logger& logger) : logger_(logger) {}
bool Log(StringPiece str) override { return logger_.Log(str); }
bool Log(const char* fmt, va_list args) override {
return logger_.Logv(fmt, args);
}
bool enabled() const override { return logger_.enabled(); }
const Logger& logger_;
};
struct TeeBackend : public Logger::Backend {
TeeBackend(const Logger& a, const Logger& b) : a_(a), b_(b) {}
bool enabled() const override { return a_.enabled() || b_.enabled(); }
bool Log(StringPiece str) override {
bool result_a = a_.Log(str);
bool result_b = b_.Log(str);
return result_a || result_b;
}
const Logger& a_;
const Logger& b_;
};
} // namespace
// Default Logger::Backend::Log implementation uses StringFormat()
// which creates a temporary string. Derived classes may want to
// override this for better performance.
bool Logger::Backend::Log(const char* fmt, va_list args) {
std::string message = StringFormat(fmt, args);
return this->Log(StringPiece(message));
}
bool Logger::enabled() const {
if (!backend_)
return false;
return backend_->enabled();
}
bool Logger::Log(const char* fmt, ...) const {
if (!backend_)
return false;
va_list args;
va_start(args, fmt);
bool result = backend_->Log(fmt, args);
va_end(args);
return result;
}
bool Logger::Log(StringPiece message) const {
if (!backend_)
return false;
return backend_->Log(message);
}
bool Logger::Logv(const char* fmt, va_list args) const {
if (!backend_)
return false;
return backend_->Log(fmt, args);
}
// static
Logger Logger::CreateForStdio(FILE* stream) {
return Logger(new StdioBackend(stream));
}
// static
Logger Logger::CreateForStd(std::ostream& out) {
return Logger(new StdOstreamBackend(out));
}
// static
Logger Logger::CreateForString(std::string* messages) {
return Logger(new StringBackend(*messages));
}
// static
Logger Logger::CreateProxyFor(const Logger& logger) {
return Logger(new ProxyBackend(logger));
}
// static
Logger Logger::CreateTeeFor(const Logger& logger_a, const Logger& logger_b) {
return Logger(new TeeBackend(logger_a, logger_b));
}
// static
Logger Logger::CreateForBackend(std::unique_ptr<Backend> backend) {
return Logger(std::move(backend));
}