//===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBStream.h"

#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"

using namespace lldb;
using namespace lldb_private;

SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {}

SBStream::SBStream(SBStream &&rhs)
    : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {}

SBStream::~SBStream() {}

bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); }

// If this stream is not redirected to a file, it will maintain a local
// cache for the stream data which can be accessed using this accessor.
const char *SBStream::GetData() {
  if (m_is_file || m_opaque_ap.get() == NULL)
    return NULL;

  return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
}

// If this stream is not redirected to a file, it will maintain a local
// cache for the stream output whose length can be accessed using this
// accessor.
size_t SBStream::GetSize() {
  if (m_is_file || m_opaque_ap.get() == NULL)
    return 0;

  return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
}

void SBStream::Printf(const char *format, ...) {
  if (!format)
    return;
  va_list args;
  va_start(args, format);
  ref().PrintfVarArg(format, args);
  va_end(args);
}

void SBStream::RedirectToFile(const char *path, bool append) {
  if (path == nullptr)
    return;

  std::string local_data;
  if (m_opaque_ap.get()) {
    // See if we have any locally backed data. If so, copy it so we can then
    // redirect it to the file so we don't lose the data
    if (!m_is_file)
      local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
  }
  StreamFile *stream_file = new StreamFile;
  uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
  if (append)
    open_options |= File::eOpenOptionAppend;
  else
    open_options |= File::eOpenOptionTruncate;
  stream_file->GetFile().Open(path, open_options,
                              lldb::eFilePermissionsFileDefault);

  m_opaque_ap.reset(stream_file);

  if (m_opaque_ap.get()) {
    m_is_file = true;

    // If we had any data locally in our StreamString, then pass that along to
    // the to new file we are redirecting to.
    if (!local_data.empty())
      m_opaque_ap->Write(&local_data[0], local_data.size());
  } else
    m_is_file = false;
}

void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
  if (fh == nullptr)
    return;

  std::string local_data;
  if (m_opaque_ap.get()) {
    // See if we have any locally backed data. If so, copy it so we can then
    // redirect it to the file so we don't lose the data
    if (!m_is_file)
      local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
  }
  m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership));

  if (m_opaque_ap.get()) {
    m_is_file = true;

    // If we had any data locally in our StreamString, then pass that along to
    // the to new file we are redirecting to.
    if (!local_data.empty())
      m_opaque_ap->Write(&local_data[0], local_data.size());
  } else
    m_is_file = false;
}

void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
  std::string local_data;
  if (m_opaque_ap.get()) {
    // See if we have any locally backed data. If so, copy it so we can then
    // redirect it to the file so we don't lose the data
    if (!m_is_file)
      local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
  }

  m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
  if (m_opaque_ap.get()) {
    m_is_file = true;

    // If we had any data locally in our StreamString, then pass that along to
    // the to new file we are redirecting to.
    if (!local_data.empty())
      m_opaque_ap->Write(&local_data[0], local_data.size());
  } else
    m_is_file = false;
}

lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); }

lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); }

lldb_private::Stream &SBStream::ref() {
  if (m_opaque_ap.get() == NULL)
    m_opaque_ap.reset(new StreamString());
  return *m_opaque_ap.get();
}

void SBStream::Clear() {
  if (m_opaque_ap.get()) {
    // See if we have any locally backed data. If so, copy it so we can then
    // redirect it to the file so we don't lose the data
    if (m_is_file)
      m_opaque_ap.reset();
    else
      static_cast<StreamString *>(m_opaque_ap.get())->Clear();
  }
}
