// Copyright 2022 The Abseil Authors.
//
// 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
//
//      https://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.
//
// -----------------------------------------------------------------------------
// File: log/log_streamer.h
// -----------------------------------------------------------------------------
//
// This header declares the class `LogStreamer` and convenience functions to
// construct LogStreamer objects with different associated log severity levels.

#ifndef ABSL_LOG_LOG_STREAMER_H_
#define ABSL_LOG_LOG_STREAMER_H_

#include <ios>
#include <memory>
#include <ostream>
#include <string>
#include <utility>

#include "absl/base/config.h"
#include "absl/base/log_severity.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/strings/internal/ostringstream.h"
#include "absl/strings/string_view.h"

namespace absl {
ABSL_NAMESPACE_BEGIN

// LogStreamer
//
// Although you can stream into `LOG(INFO)`, you can't pass it into a function
// that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
// `std::ostream` that buffers everything that's streamed in.  The buffer's
// contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
// If nothing is streamed in, an empty message is logged.  If the specified
// severity is `absl::LogSeverity::kFatal`, the program will be terminated when
// the `LogStreamer` is destroyed regardless of whether any data were streamed
// in.
//
// Factory functions corresponding to the `absl::LogSeverity` enumerators
// are provided for convenience; if the desired severity is variable, invoke the
// constructor directly.
//
// LogStreamer is movable, but not copyable.
//
// Examples:
//
//   ShaveYakAndWriteToStream(
//       yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());
//
//   {
//     // This logs a single line containing data streamed by all three function
//     // calls.
//     absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);
//     ShaveYakAndWriteToStream(yak1, streamer.stream());
//     streamer.stream() << " ";
//     ShaveYakAndWriteToStream(yak2, streamer.stream());
//     streamer.stream() << " ";
//     ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
//   }
class LogStreamer final {
 public:
  // LogStreamer::LogStreamer()
  //
  // Creates a LogStreamer with a given `severity` that will log a message
  // attributed to the given `file` and `line`.
  explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,
                       int line)
      : severity_(severity),
        line_(line),
        file_(file),
        stream_(
            absl::make_unique<absl::strings_internal::OStringStream>(&buf_)) {
    // To match `LOG`'s defaults:
    stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
  }

  // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
  // and a program that streams into one has undefined behavior.
  LogStreamer(LogStreamer&& that) noexcept
      : severity_(that.severity_),
        line_(that.line_),
        file_(std::move(that.file_)),
        buf_(std::move(that.buf_)),
        stream_(that.stream_
                    ? absl::make_unique<absl::strings_internal::OStringStream>(
                          &buf_)
                    : nullptr) {
    that.stream_.reset();
  }
  LogStreamer& operator=(LogStreamer&& that) {
    LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
    severity_ = that.severity_;
    file_ = std::move(that.file_);
    line_ = that.line_;
    buf_ = std::move(that.buf_);
    stream_ =
        that.stream_
            ? absl::make_unique<absl::strings_internal::OStringStream>(&buf_)
            : nullptr;
    that.stream_.reset();
    return *this;
  }

  // LogStreamer::~LogStreamer()
  //
  // Logs this LogStreamer's buffered content as if by LOG.
  ~LogStreamer() {
    LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
  }

  // LogStreamer::stream()
  //
  // Returns the `std::ostream` to use to write into this LogStreamer' internal
  // buffer.
  std::ostream& stream() { return *stream_; }

 private:
  absl::LogSeverity severity_;
  int line_;
  std::string file_;
  std::string buf_;
  // TODO(durandal): de-pointerize this once we are off of our old mostly-C++11
  // libstdc++ (which lacks move constructors for std streams).
  // `stream_` is null in a moved-from `LogStreamer`; this is in fact how we
  // recognize one to avoid logging when it is destroyed or reassigned.
  std::unique_ptr<absl::strings_internal::OStringStream> stream_;
};

// LogInfoStreamer()
//
// Returns a LogStreamer that writes at level LogSeverity::kInfo.
inline LogStreamer LogInfoStreamer(absl::string_view file, int line) {
  return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);
}

// LogWarningStreamer()
//
// Returns a LogStreamer that writes at level LogSeverity::kWarning.
inline LogStreamer LogWarningStreamer(absl::string_view file, int line) {
  return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);
}

// LogErrorStreamer()
//
// Returns a LogStreamer that writes at level LogSeverity::kError.
inline LogStreamer LogErrorStreamer(absl::string_view file, int line) {
  return absl::LogStreamer(absl::LogSeverity::kError, file, line);
}

// LogFatalStreamer()
//
// Returns a LogStreamer that writes at level LogSeverity::kFatal.
//
// The program will be terminated when this `LogStreamer` is destroyed,
// regardless of whether any data were streamed in.
inline LogStreamer LogFatalStreamer(absl::string_view file, int line) {
  return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);
}

ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_LOG_LOG_STREAMER_H_
