//===-- SBSymbolContextList.cpp -------------------------------------------===//
//
// 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/SBSymbolContextList.h"
#include "SBReproducerPrivate.h"
#include "Utils.h"
#include "lldb/API/SBStream.h"
#include "lldb/Symbol/SymbolContext.h"

using namespace lldb;
using namespace lldb_private;

SBSymbolContextList::SBSymbolContextList()
    : m_opaque_up(new SymbolContextList()) {
  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSymbolContextList);
}

SBSymbolContextList::SBSymbolContextList(const SBSymbolContextList &rhs)
    : m_opaque_up() {
  LLDB_RECORD_CONSTRUCTOR(SBSymbolContextList,
                          (const lldb::SBSymbolContextList &), rhs);

  m_opaque_up = clone(rhs.m_opaque_up);
}

SBSymbolContextList::~SBSymbolContextList() = default;

const SBSymbolContextList &SBSymbolContextList::
operator=(const SBSymbolContextList &rhs) {
  LLDB_RECORD_METHOD(
      const lldb::SBSymbolContextList &,
      SBSymbolContextList, operator=,(const lldb::SBSymbolContextList &), rhs);

  if (this != &rhs)
    m_opaque_up = clone(rhs.m_opaque_up);
  return LLDB_RECORD_RESULT(*this);
}

uint32_t SBSymbolContextList::GetSize() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBSymbolContextList, GetSize);

  if (m_opaque_up)
    return m_opaque_up->GetSize();
  return 0;
}

SBSymbolContext SBSymbolContextList::GetContextAtIndex(uint32_t idx) {
  LLDB_RECORD_METHOD(lldb::SBSymbolContext, SBSymbolContextList,
                     GetContextAtIndex, (uint32_t), idx);

  SBSymbolContext sb_sc;
  if (m_opaque_up) {
    SymbolContext sc;
    if (m_opaque_up->GetContextAtIndex(idx, sc)) {
      sb_sc.SetSymbolContext(&sc);
    }
  }
  return LLDB_RECORD_RESULT(sb_sc);
}

void SBSymbolContextList::Clear() {
  LLDB_RECORD_METHOD_NO_ARGS(void, SBSymbolContextList, Clear);

  if (m_opaque_up)
    m_opaque_up->Clear();
}

void SBSymbolContextList::Append(SBSymbolContext &sc) {
  LLDB_RECORD_METHOD(void, SBSymbolContextList, Append,
                     (lldb::SBSymbolContext &), sc);

  if (sc.IsValid() && m_opaque_up.get())
    m_opaque_up->Append(*sc);
}

void SBSymbolContextList::Append(SBSymbolContextList &sc_list) {
  LLDB_RECORD_METHOD(void, SBSymbolContextList, Append,
                     (lldb::SBSymbolContextList &), sc_list);

  if (sc_list.IsValid() && m_opaque_up.get())
    m_opaque_up->Append(*sc_list);
}

bool SBSymbolContextList::IsValid() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbolContextList, IsValid);
  return this->operator bool();
}
SBSymbolContextList::operator bool() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbolContextList, operator bool);

  return m_opaque_up != nullptr;
}

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

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

bool SBSymbolContextList::GetDescription(lldb::SBStream &description) {
  LLDB_RECORD_METHOD(bool, SBSymbolContextList, GetDescription,
                     (lldb::SBStream &), description);

  Stream &strm = description.ref();
  if (m_opaque_up)
    m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, nullptr);
  return true;
}

namespace lldb_private {
namespace repro {

template <>
void RegisterMethods<SBSymbolContextList>(Registry &R) {
  LLDB_REGISTER_CONSTRUCTOR(SBSymbolContextList, ());
  LLDB_REGISTER_CONSTRUCTOR(SBSymbolContextList,
                            (const lldb::SBSymbolContextList &));
  LLDB_REGISTER_METHOD(
      const lldb::SBSymbolContextList &,
      SBSymbolContextList, operator=,(const lldb::SBSymbolContextList &));
  LLDB_REGISTER_METHOD_CONST(uint32_t, SBSymbolContextList, GetSize, ());
  LLDB_REGISTER_METHOD(lldb::SBSymbolContext, SBSymbolContextList,
                       GetContextAtIndex, (uint32_t));
  LLDB_REGISTER_METHOD(void, SBSymbolContextList, Clear, ());
  LLDB_REGISTER_METHOD(void, SBSymbolContextList, Append,
                       (lldb::SBSymbolContext &));
  LLDB_REGISTER_METHOD(void, SBSymbolContextList, Append,
                       (lldb::SBSymbolContextList &));
  LLDB_REGISTER_METHOD_CONST(bool, SBSymbolContextList, IsValid, ());
  LLDB_REGISTER_METHOD_CONST(bool, SBSymbolContextList, operator bool, ());
  LLDB_REGISTER_METHOD(bool, SBSymbolContextList, GetDescription,
                       (lldb::SBStream &));
}

}
}
