//===-- 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 (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%llx", 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())
        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;
}

