//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugPubnamesSet.h"

#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"

#include "SymbolFileDWARF.h"

using namespace lldb_private;

DWARFDebugPubnamesSet::DWARFDebugPubnamesSet()
    : m_offset(DW_INVALID_OFFSET), m_header(), m_descriptors(),
      m_name_to_descriptor_index() {}

DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,
                                             dw_offset_t cu_die_offset,
                                             dw_offset_t cu_die_length)
    : m_offset(debug_aranges_offset), m_header(), m_descriptors(),
      m_name_to_descriptor_index() {
  m_header.length =
      10; // set the length to only include the header right for now
  m_header.version = 2;                // The DWARF version number
  m_header.die_offset = cu_die_offset; // compile unit .debug_info offset
  m_header.die_length = cu_die_length; // compile unit .debug_info length
}

void DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset,
                                          const char *name) {
  if (name && name[0]) {
    // Adjust our header length
    m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
    Descriptor pubnameDesc(cu_rel_offset, name);
    m_descriptors.push_back(pubnameDesc);
  }
}

void DWARFDebugPubnamesSet::Clear() {
  m_offset = DW_INVALID_OFFSET;
  m_header.length = 10;
  m_header.version = 2;
  m_header.die_offset = DW_INVALID_OFFSET;
  m_header.die_length = 0;
  m_descriptors.clear();
}

//----------------------------------------------------------------------
// InitNameIndexes
//----------------------------------------------------------------------
void DWARFDebugPubnamesSet::InitNameIndexes() const {
  // Create the name index vector to be able to quickly search by name
  const size_t count = m_descriptors.size();
  for (uint32_t idx = 0; idx < count; ++idx) {
    const char *name = m_descriptors[idx].name.c_str();
    if (name && name[0])
      m_name_to_descriptor_index.insert(
          cstr_to_index_mmap::value_type(name, idx));
  }
}

bool DWARFDebugPubnamesSet::Extract(const DWARFDataExtractor &data,
                                    lldb::offset_t *offset_ptr) {
  if (data.ValidOffset(*offset_ptr)) {
    m_descriptors.clear();
    m_offset = *offset_ptr;
    m_header.length = data.GetDWARFInitialLength(offset_ptr);
    m_header.version = data.GetU16(offset_ptr);
    m_header.die_offset = data.GetDWARFOffset(offset_ptr);
    m_header.die_length = data.GetDWARFOffset(offset_ptr);

    Descriptor pubnameDesc;
    while (data.ValidOffset(*offset_ptr)) {
      pubnameDesc.offset = data.GetDWARFOffset(offset_ptr);

      if (pubnameDesc.offset) {
        const char *name = data.GetCStr(offset_ptr);
        if (name && name[0]) {
          pubnameDesc.name = name;
          m_descriptors.push_back(pubnameDesc);
        }
      } else
        break; // We are done if we get a zero 4 byte offset
    }

    return !m_descriptors.empty();
  }
  return false;
}

dw_offset_t DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const {
  return m_offset + m_header.length + 4;
}

void DWARFDebugPubnamesSet::Dump(Log *log) const {
  log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, "
              "die_offset = 0x%8.8x, die_length = 0x%8.8x",
              m_header.length, m_header.version, m_header.die_offset,
              m_header.die_length);

  bool verbose = log->GetVerbose();

  DescriptorConstIter pos;
  DescriptorConstIter end = m_descriptors.end();
  for (pos = m_descriptors.begin(); pos != end; ++pos) {
    if (verbose)
      log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset,
                  m_header.die_offset, pos->offset + m_header.die_offset,
                  pos->name.c_str());
    else
      log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset,
                  pos->name.c_str());
  }
}

void DWARFDebugPubnamesSet::Find(
    const char *name, bool ignore_case,
    std::vector<dw_offset_t> &die_offset_coll) const {
  if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
    InitNameIndexes();

  std::pair<cstr_to_index_mmap::const_iterator,
            cstr_to_index_mmap::const_iterator>
      range(m_name_to_descriptor_index.equal_range(name));
  for (cstr_to_index_mmap::const_iterator pos = range.first;
       pos != range.second; ++pos)
    die_offset_coll.push_back(m_header.die_offset +
                              m_descriptors[(*pos).second].offset);
}

void DWARFDebugPubnamesSet::Find(
    const RegularExpression &regex,
    std::vector<dw_offset_t> &die_offset_coll) const {
  DescriptorConstIter pos;
  DescriptorConstIter end = m_descriptors.end();
  for (pos = m_descriptors.begin(); pos != end; ++pos) {
    if (regex.Execute(pos->name))
      die_offset_coll.push_back(m_header.die_offset + pos->offset);
  }
}
