//===-- SBSymbolContext.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/SBSymbolContext.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"

using namespace lldb;
using namespace lldb_private;



SBSymbolContext::SBSymbolContext () :
    m_opaque_ap ()
{
}

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

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

SBSymbolContext::~SBSymbolContext ()
{
}

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

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

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



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

    SBModule sb_module;
    ModuleSP module_sp;
    if (m_opaque_ap.get())
    {
        module_sp = m_opaque_ap->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_ap.get()),
                     static_cast<void*>(module_sp.get()), sstr.GetData());
    }

    return sb_module;
}

SBCompileUnit
SBSymbolContext::GetCompileUnit ()
{
    return SBCompileUnit (m_opaque_ap.get() ? m_opaque_ap->comp_unit : NULL);
}

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

    Function *function = NULL;

    if (m_opaque_ap.get())
        function = m_opaque_ap->function;

    SBFunction sb_function (function);

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

    return sb_function;
}

SBBlock
SBSymbolContext::GetBlock ()
{
    return SBBlock (m_opaque_ap.get() ? m_opaque_ap->block : NULL);
}

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

    SBLineEntry sb_line_entry;
    if (m_opaque_ap.get())
        sb_line_entry.SetLineEntry (m_opaque_ap->line_entry);

    if (log)
    {
        log->Printf ("SBSymbolContext(%p)::GetLineEntry () => SBLineEntry(%p)",
                     static_cast<void*>(m_opaque_ap.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_ap.get())
        symbol = m_opaque_ap->symbol;

    SBSymbol sb_symbol (symbol);

    if (log)
        log->Printf ("SBSymbolContext(%p)::GetSymbol () => SBSymbol(%p)",
                     static_cast<void*>(m_opaque_ap.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_ap.get();
}


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


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

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

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

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

    if (m_opaque_ap.get())
    {
        m_opaque_ap->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_ap.get() && curr_frame_pc.IsValid())
    {
        if (m_opaque_ap->GetParentOfInlinedScope (curr_frame_pc.ref(), sb_sc.ref(), parent_frame_addr.ref()))
            return sb_sc;
    }
    return SBSymbolContext();
}

