//===-- SBTypeEnumMember.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/SBDefines.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBTypeEnumMember.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/Type.h"

using namespace lldb;
using namespace lldb_private;
using namespace clang;

SBTypeEnumMember::SBTypeEnumMember() :
    m_opaque_sp()
{
}

SBTypeEnumMember::~SBTypeEnumMember()
{
}
SBTypeEnumMember::SBTypeEnumMember (const lldb::TypeEnumMemberImplSP &enum_member_sp) :
    m_opaque_sp(enum_member_sp)
{
}

SBTypeEnumMember::SBTypeEnumMember (const SBTypeEnumMember& rhs) :
    m_opaque_sp()
{
    if (this != &rhs)
    {
        if (rhs.IsValid())
            m_opaque_sp.reset(new TypeEnumMemberImpl(rhs.ref()));
    }
}

SBTypeEnumMember&
SBTypeEnumMember::operator = (const SBTypeEnumMember& rhs)
{
    if (this != &rhs)
    {
        if (rhs.IsValid())
            m_opaque_sp.reset(new TypeEnumMemberImpl(rhs.ref()));
    }
    return *this;
}

bool
SBTypeEnumMember::IsValid() const
{
    return m_opaque_sp.get();
}

const char *
SBTypeEnumMember::GetName ()
{
    if (m_opaque_sp.get())
        return m_opaque_sp->GetName().GetCString();
    return NULL;
}

int64_t
SBTypeEnumMember::GetValueAsSigned()
{
    if (m_opaque_sp.get())
        return m_opaque_sp->GetValueAsSigned();
    return 0;
}

uint64_t
SBTypeEnumMember::GetValueAsUnsigned()
{
    if (m_opaque_sp.get())
        return m_opaque_sp->GetValueAsUnsigned();
    return 0;
}

SBType
SBTypeEnumMember::GetType ()
{
    SBType sb_type;
    if (m_opaque_sp.get())
    {
        sb_type.SetSP(m_opaque_sp->GetIntegerType());
    }
    return sb_type;

}

void
SBTypeEnumMember::reset(TypeEnumMemberImpl *type_member_impl)
{
    m_opaque_sp.reset(type_member_impl);
}

TypeEnumMemberImpl &
SBTypeEnumMember::ref ()
{
    if (m_opaque_sp.get() == NULL)
        m_opaque_sp.reset (new TypeEnumMemberImpl());
    return *m_opaque_sp.get();
}

const TypeEnumMemberImpl &
SBTypeEnumMember::ref () const
{
    return *m_opaque_sp.get();
}


SBTypeEnumMemberList::SBTypeEnumMemberList() :
    m_opaque_ap(new TypeEnumMemberListImpl())
{
}

SBTypeEnumMemberList::SBTypeEnumMemberList(const SBTypeEnumMemberList& rhs) :
    m_opaque_ap(new TypeEnumMemberListImpl())
{
    for (uint32_t i = 0, rhs_size = const_cast<SBTypeEnumMemberList&>(rhs).GetSize(); i < rhs_size; i++)
        Append(const_cast<SBTypeEnumMemberList&>(rhs).GetTypeEnumMemberAtIndex(i));
}

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

SBTypeEnumMemberList&
SBTypeEnumMemberList::operator = (const SBTypeEnumMemberList& rhs)
{
    if (this != &rhs)
    {
        m_opaque_ap.reset (new TypeEnumMemberListImpl());
        for (uint32_t i = 0, rhs_size = const_cast<SBTypeEnumMemberList&>(rhs).GetSize(); i < rhs_size; i++)
            Append(const_cast<SBTypeEnumMemberList&>(rhs).GetTypeEnumMemberAtIndex(i));
    }
    return *this;
}

void
SBTypeEnumMemberList::Append (SBTypeEnumMember enum_member)
{
    if (enum_member.IsValid())
        m_opaque_ap->Append (enum_member.m_opaque_sp);
}

SBTypeEnumMember
SBTypeEnumMemberList::GetTypeEnumMemberAtIndex(uint32_t index)
{
    if (m_opaque_ap.get())
        return SBTypeEnumMember(m_opaque_ap->GetTypeEnumMemberAtIndex(index));
    return SBTypeEnumMember();
}

uint32_t
SBTypeEnumMemberList::GetSize()
{
    return m_opaque_ap->GetSize();
}

SBTypeEnumMemberList::~SBTypeEnumMemberList()
{
}

bool
SBTypeEnumMember::GetDescription (lldb::SBStream &description, 
                                  lldb::DescriptionLevel description_level)
{
    Stream &strm = description.ref();

    if (m_opaque_sp.get())
    {
        if( m_opaque_sp->GetIntegerType()->GetDescription(strm, description_level) )
        {
            strm.Printf(" %s", m_opaque_sp->GetName().GetCString());
        }
    }
    else
    {
        strm.PutCString ("No value");
    }
    return true;
}
