//===-- SBAddress.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/SBAddress.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Target.h"


using namespace lldb;
using namespace lldb_private;


SBAddress::SBAddress () :
    m_opaque_ap ()
{
}

SBAddress::SBAddress (const Address *lldb_object_ptr) :
    m_opaque_ap ()
{
    if (lldb_object_ptr)
        ref() = *lldb_object_ptr;
}

SBAddress::SBAddress (const SBAddress &rhs) :
    m_opaque_ap ()
{
    if (rhs.IsValid())
        ref() = rhs.ref();
}


SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) :
    m_opaque_ap(new Address (section.GetSP(), offset))
{
}

// Create an address by resolving a load address using the supplied target
SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
    m_opaque_ap()
{    
    SetLoadAddress (load_addr, target);
}



SBAddress::~SBAddress ()
{
}

const SBAddress &
SBAddress::operator = (const SBAddress &rhs)
{
    if (this != &rhs)
    {
        if (rhs.IsValid())
            ref() = rhs.ref();
        else
            m_opaque_ap.reset();
    }
    return *this;
}

bool
SBAddress::IsValid () const
{
    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
}

void
SBAddress::Clear ()
{
    m_opaque_ap.reset();
}

void
SBAddress::SetAddress (lldb::SBSection section, lldb::addr_t offset)
{
    Address &addr = ref();
    addr.SetSection (section.GetSP());
    addr.SetOffset (offset);
}


void
SBAddress::SetAddress (const Address *lldb_object_ptr)
{
    if (lldb_object_ptr)
        ref() =  *lldb_object_ptr;
    else
        m_opaque_ap.reset();
}

lldb::addr_t
SBAddress::GetFileAddress () const
{
    if (m_opaque_ap.get())
        return m_opaque_ap->GetFileAddress();
    else
        return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
SBAddress::GetLoadAddress (const SBTarget &target) const
{
    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
    TargetSP target_sp (target.GetSP());
    if (target_sp)
    {
        if (m_opaque_ap.get())
        {
            Mutex::Locker api_locker (target_sp->GetAPIMutex());
            addr = m_opaque_ap->GetLoadAddress (target_sp.get());
        }
    }
    
    if (log)
    {
        if (addr == LLDB_INVALID_ADDRESS)
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS", target_sp.get());
        else
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%" PRIx64, target_sp.get(), addr);
    }

    return addr;
}

void
SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
{
    // Create the address object if we don't already have one
    ref();
    if (target.IsValid())
        *this = target.ResolveLoadAddress(load_addr);
    else
        m_opaque_ap->Clear();

    // Check if we weren't were able to resolve a section offset address.
    // If we weren't it is ok, the load address might be a location on the
    // stack or heap, so we should just have an address with no section and
    // a valid offset
    if (!m_opaque_ap->IsValid())
        m_opaque_ap->SetOffset(load_addr);
}

bool
SBAddress::OffsetAddress (addr_t offset)
{
    if (m_opaque_ap.get())
    {
        addr_t addr_offset = m_opaque_ap->GetOffset();
        if (addr_offset != LLDB_INVALID_ADDRESS)
        {
            m_opaque_ap->SetOffset(addr_offset + offset);
            return true;
        }
    }
    return false;
}

lldb::SBSection
SBAddress::GetSection ()
{
    lldb::SBSection sb_section;
    if (m_opaque_ap.get())
        sb_section.SetSP (m_opaque_ap->GetSection());
    return sb_section;
}

lldb::addr_t
SBAddress::GetOffset ()
{
    if (m_opaque_ap.get())
        return m_opaque_ap->GetOffset();
    return 0;
}

Address *
SBAddress::operator->()
{
    return m_opaque_ap.get();
}

const Address *
SBAddress::operator->() const
{
    return m_opaque_ap.get();
}

Address &
SBAddress::ref ()
{
    if (m_opaque_ap.get() == NULL)
        m_opaque_ap.reset (new Address());
    return *m_opaque_ap;
}

const Address &
SBAddress::ref () const
{
    // This object should already have checked with "IsValid()" 
    // prior to calling this function. In case you didn't we will assert
    // and die to let you know.
    assert (m_opaque_ap.get());
    return *m_opaque_ap;
}

Address *
SBAddress::get ()
{
    return m_opaque_ap.get();
}

bool
SBAddress::GetDescription (SBStream &description)
{
    // Call "ref()" on the stream to make sure it creates a backing stream in
    // case there isn't one already...
    Stream &strm = description.ref();
    if (m_opaque_ap.get())
    {
        m_opaque_ap->Dump (&strm,
                           NULL,
                           Address::DumpStyleResolvedDescription,
                           Address::DumpStyleModuleWithFileAddress,
                           4);
        StreamString sstrm;
//        m_opaque_ap->Dump (&sstrm, NULL, Address::DumpStyleResolvedDescription, Address::DumpStyleInvalid, 4);
//        if (sstrm.GetData())
//            strm.Printf (" (%s)", sstrm.GetData());
    }
    else
        strm.PutCString ("No value");

    return true;
}

SBModule
SBAddress::GetModule ()
{
    SBModule sb_module;
    if (m_opaque_ap.get())
        sb_module.SetSP (m_opaque_ap->GetModule());
    return sb_module;
}

SBSymbolContext
SBAddress::GetSymbolContext (uint32_t resolve_scope)
{
    SBSymbolContext sb_sc;
    if (m_opaque_ap.get())
        m_opaque_ap->CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
    return sb_sc;
}

SBCompileUnit
SBAddress::GetCompileUnit ()
{
    SBCompileUnit sb_comp_unit;
    if (m_opaque_ap.get())
        sb_comp_unit.reset(m_opaque_ap->CalculateSymbolContextCompileUnit());
    return sb_comp_unit;
}

SBFunction
SBAddress::GetFunction ()
{
    SBFunction sb_function;
    if (m_opaque_ap.get())
        sb_function.reset(m_opaque_ap->CalculateSymbolContextFunction());
    return sb_function;
}

SBBlock
SBAddress::GetBlock ()
{
    SBBlock sb_block;
    if (m_opaque_ap.get())
        sb_block.SetPtr(m_opaque_ap->CalculateSymbolContextBlock());
    return sb_block;
}

SBSymbol
SBAddress::GetSymbol ()
{
    SBSymbol sb_symbol;
    if (m_opaque_ap.get())
        sb_symbol.reset(m_opaque_ap->CalculateSymbolContextSymbol());
    return sb_symbol;
}

SBLineEntry
SBAddress::GetLineEntry ()
{
    SBLineEntry sb_line_entry;
    if (m_opaque_ap.get())
    {
        LineEntry line_entry;
        if (m_opaque_ap->CalculateSymbolContextLineEntry (line_entry))
            sb_line_entry.SetLineEntry (line_entry);
    }
    return sb_line_entry;
}

AddressClass
SBAddress::GetAddressClass ()
{
    if (m_opaque_ap.get())
        return m_opaque_ap->GetAddressClass();
    return eAddressClassInvalid;
}

