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

#include <inttypes.h> // PRIu64
#include <limits.h>

#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Host/FileSpec.h"

#include "llvm/ADT/SmallString.h"

using namespace lldb;
using namespace lldb_private;

SBFileSpec::SBFileSpec() : m_opaque_ap(new lldb_private::FileSpec()) {}

SBFileSpec::SBFileSpec(const SBFileSpec &rhs)
    : m_opaque_ap(new lldb_private::FileSpec(*rhs.m_opaque_ap)) {}

SBFileSpec::SBFileSpec(const lldb_private::FileSpec &fspec)
    : m_opaque_ap(new lldb_private::FileSpec(fspec)) {}

// Deprecated!!!
SBFileSpec::SBFileSpec(const char *path)
    : m_opaque_ap(new FileSpec(path, true)) {}

SBFileSpec::SBFileSpec(const char *path, bool resolve)
    : m_opaque_ap(new FileSpec(path, resolve)) {}

SBFileSpec::~SBFileSpec() {}

const SBFileSpec &SBFileSpec::operator=(const SBFileSpec &rhs) {
  if (this != &rhs)
    *m_opaque_ap = *rhs.m_opaque_ap;
  return *this;
}

bool SBFileSpec::IsValid() const { return m_opaque_ap->operator bool(); }

bool SBFileSpec::Exists() const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  bool result = m_opaque_ap->Exists();

  if (log)
    log->Printf("SBFileSpec(%p)::Exists () => %s",
                static_cast<void *>(m_opaque_ap.get()),
                (result ? "true" : "false"));

  return result;
}

bool SBFileSpec::ResolveExecutableLocation() {
  return m_opaque_ap->ResolveExecutableLocation();
}

int SBFileSpec::ResolvePath(const char *src_path, char *dst_path,
                            size_t dst_len) {
  llvm::SmallString<64> result(src_path);
  lldb_private::FileSpec::Resolve(result);
  ::snprintf(dst_path, dst_len, "%s", result.c_str());
  return std::min(dst_len - 1, result.size());
}

const char *SBFileSpec::GetFilename() const {
  const char *s = m_opaque_ap->GetFilename().AsCString();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    if (s)
      log->Printf("SBFileSpec(%p)::GetFilename () => \"%s\"",
                  static_cast<void *>(m_opaque_ap.get()), s);
    else
      log->Printf("SBFileSpec(%p)::GetFilename () => NULL",
                  static_cast<void *>(m_opaque_ap.get()));
  }

  return s;
}

const char *SBFileSpec::GetDirectory() const {
  FileSpec directory{*m_opaque_ap};
  directory.GetFilename().Clear();
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    if (directory)
      log->Printf("SBFileSpec(%p)::GetDirectory () => \"%s\"",
                  static_cast<void *>(m_opaque_ap.get()),
                  directory.GetCString());
    else
      log->Printf("SBFileSpec(%p)::GetDirectory () => NULL",
                  static_cast<void *>(m_opaque_ap.get()));
  }
  return directory.GetCString();
}

void SBFileSpec::SetFilename(const char *filename) {
  if (filename && filename[0])
    m_opaque_ap->GetFilename().SetCString(filename);
  else
    m_opaque_ap->GetFilename().Clear();
}

void SBFileSpec::SetDirectory(const char *directory) {
  if (directory && directory[0])
    m_opaque_ap->GetDirectory().SetCString(directory);
  else
    m_opaque_ap->GetDirectory().Clear();
}

uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  uint32_t result = m_opaque_ap->GetPath(dst_path, dst_len);

  if (log)
    log->Printf("SBFileSpec(%p)::GetPath (dst_path=\"%.*s\", dst_len=%" PRIu64
                ") => %u",
                static_cast<void *>(m_opaque_ap.get()), result, dst_path,
                static_cast<uint64_t>(dst_len), result);

  if (result == 0 && dst_path && dst_len > 0)
    *dst_path = '\0';
  return result;
}

const lldb_private::FileSpec *SBFileSpec::operator->() const {
  return m_opaque_ap.get();
}

const lldb_private::FileSpec *SBFileSpec::get() const {
  return m_opaque_ap.get();
}

const lldb_private::FileSpec &SBFileSpec::operator*() const {
  return *m_opaque_ap.get();
}

const lldb_private::FileSpec &SBFileSpec::ref() const {
  return *m_opaque_ap.get();
}

void SBFileSpec::SetFileSpec(const lldb_private::FileSpec &fs) {
  *m_opaque_ap = fs;
}

bool SBFileSpec::GetDescription(SBStream &description) const {
  Stream &strm = description.ref();
  char path[PATH_MAX];
  if (m_opaque_ap->GetPath(path, sizeof(path)))
    strm.PutCString(path);
  return true;
}

void SBFileSpec::AppendPathComponent(const char *fn) {
  m_opaque_ap->AppendPathComponent(fn);
}
