//===-- SBSymbolContext.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

SBSymbolContext::SBSymbolContext() : m_opaque_up() {}

SBSymbolContext::SBSymbolContext(const SymbolContext *sc_ptr) : m_opaque_up() {
  if (sc_ptr)
    m_opaque_up.reset(new SymbolContext(*sc_ptr));
}

SBSymbolContext::SBSymbolContext(const SBSymbolContext &rhs) : m_opaque_up() {
  if (rhs.IsValid()) {
    if (m_opaque_up)
      *m_opaque_up = *rhs.m_opaque_up;
    else
      ref() = *rhs.m_opaque_up;
  }
}

SBSymbolContext::~SBSymbolContext() {}

const SBSymbolContext &SBSymbolContext::operator=(const SBSymbolContext &rhs) {
  if (this != &rhs) {
    if (rhs.IsValid())
      m_opaque_up.reset(new lldb_private::SymbolContext(*rhs.m_opaque_up));
  }
  return *this;
}

void SBSymbolContext::SetSymbolContext(const SymbolContext *sc_ptr) {
  if (sc_ptr) {
    if (m_opaque_up)
      *m_opaque_up = *sc_ptr;
    else
      m_opaque_up.reset(new SymbolContext(*sc_ptr));
  } else {
    if (m_opaque_up)
      m_opaque_up->Clear(true);
  }
}

bool SBSymbolContext::IsValid() const { return m_opaque_up != NULL; }

SBModule SBSymbolContext::GetModule() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBModule sb_module;
  ModuleSP module_sp;
  if (m_opaque_up) {
    module_sp = m_opaque_up->module_sp;
    sb_module.SetSP(module_sp);
  }

  if (log) {
    SBStream sstr;
    sb_module.GetDescription(sstr);
    log->Printf("SBSymbolContext(%p)::GetModule () => SBModule(%p): %s",
                static_cast<void *>(m_opaque_up.get()),
                static_cast<void *>(module_sp.get()), sstr.GetData());
  }

  return sb_module;
}

SBCompileUnit SBSymbolContext::GetCompileUnit() {
  return SBCompileUnit(m_opaque_up ? m_opaque_up->comp_unit : NULL);
}

SBFunction SBSymbolContext::GetFunction() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  Function *function = NULL;

  if (m_opaque_up)
    function = m_opaque_up->function;

  SBFunction sb_function(function);

  if (log)
    log->Printf("SBSymbolContext(%p)::GetFunction () => SBFunction(%p)",
                static_cast<void *>(m_opaque_up.get()),
                static_cast<void *>(function));

  return sb_function;
}

SBBlock SBSymbolContext::GetBlock() {
  return SBBlock(m_opaque_up ? m_opaque_up->block : NULL);
}

SBLineEntry SBSymbolContext::GetLineEntry() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBLineEntry sb_line_entry;
  if (m_opaque_up)
    sb_line_entry.SetLineEntry(m_opaque_up->line_entry);

  if (log) {
    log->Printf("SBSymbolContext(%p)::GetLineEntry () => SBLineEntry(%p)",
                static_cast<void *>(m_opaque_up.get()),
                static_cast<void *>(sb_line_entry.get()));
  }

  return sb_line_entry;
}

SBSymbol SBSymbolContext::GetSymbol() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  Symbol *symbol = NULL;

  if (m_opaque_up)
    symbol = m_opaque_up->symbol;

  SBSymbol sb_symbol(symbol);

  if (log)
    log->Printf("SBSymbolContext(%p)::GetSymbol () => SBSymbol(%p)",
                static_cast<void *>(m_opaque_up.get()),
                static_cast<void *>(symbol));

  return sb_symbol;
}

void SBSymbolContext::SetModule(lldb::SBModule module) {
  ref().module_sp = module.GetSP();
}

void SBSymbolContext::SetCompileUnit(lldb::SBCompileUnit compile_unit) {
  ref().comp_unit = compile_unit.get();
}

void SBSymbolContext::SetFunction(lldb::SBFunction function) {
  ref().function = function.get();
}

void SBSymbolContext::SetBlock(lldb::SBBlock block) {
  ref().block = block.GetPtr();
}

void SBSymbolContext::SetLineEntry(lldb::SBLineEntry line_entry) {
  if (line_entry.IsValid())
    ref().line_entry = line_entry.ref();
  else
    ref().line_entry.Clear();
}

void SBSymbolContext::SetSymbol(lldb::SBSymbol symbol) {
  ref().symbol = symbol.get();
}

lldb_private::SymbolContext *SBSymbolContext::operator->() const {
  return m_opaque_up.get();
}

const lldb_private::SymbolContext &SBSymbolContext::operator*() const {
  assert(m_opaque_up.get());
  return *m_opaque_up;
}

lldb_private::SymbolContext &SBSymbolContext::operator*() {
  if (m_opaque_up == NULL)
    m_opaque_up.reset(new SymbolContext);
  return *m_opaque_up;
}

lldb_private::SymbolContext &SBSymbolContext::ref() {
  if (m_opaque_up == NULL)
    m_opaque_up.reset(new SymbolContext);
  return *m_opaque_up;
}

lldb_private::SymbolContext *SBSymbolContext::get() const {
  return m_opaque_up.get();
}

bool SBSymbolContext::GetDescription(SBStream &description) {
  Stream &strm = description.ref();

  if (m_opaque_up) {
    m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL);
  } else
    strm.PutCString("No value");

  return true;
}

SBSymbolContext
SBSymbolContext::GetParentOfInlinedScope(const SBAddress &curr_frame_pc,
                                         SBAddress &parent_frame_addr) const {
  SBSymbolContext sb_sc;
  if (m_opaque_up.get() && curr_frame_pc.IsValid()) {
    if (m_opaque_up->GetParentOfInlinedScope(curr_frame_pc.ref(), sb_sc.ref(),
                                             parent_frame_addr.ref()))
      return sb_sc;
  }
  return SBSymbolContext();
}
