//===-- BreakpointResolverFileRegex.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/Breakpoint/BreakpointResolverFileRegex.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// BreakpointResolverFileRegex:
//----------------------------------------------------------------------
BreakpointResolverFileRegex::BreakpointResolverFileRegex(
    Breakpoint *bkpt, RegularExpression &regex,
    const std::unordered_set<std::string> &func_names, bool exact_match)
    : BreakpointResolver(bkpt, BreakpointResolver::FileRegexResolver),
      m_regex(regex), m_exact_match(exact_match), m_function_names(func_names) {
}

BreakpointResolverFileRegex::~BreakpointResolverFileRegex() {}

BreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData(
    Breakpoint *bkpt, const StructuredData::Dictionary &options_dict,
    Status &error) {
  bool success;

  llvm::StringRef regex_string;
  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::RegexString), regex_string);
  if (!success) {
    error.SetErrorString("BRFR::CFSD: Couldn't find regex entry.");
    return nullptr;
  }
  RegularExpression regex(regex_string);

  bool exact_match;
  success = options_dict.GetValueForKeyAsBoolean(
      GetKey(OptionNames::ExactMatch), exact_match);
  if (!success) {
    error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry.");
    return nullptr;
  }

  // The names array is optional:
  std::unordered_set<std::string> names_set;
  StructuredData::Array *names_array;
  success = options_dict.GetValueForKeyAsArray(
      GetKey(OptionNames::SymbolNameArray), names_array);
  if (success && names_array) {
    size_t num_names = names_array->GetSize();
    for (size_t i = 0; i < num_names; i++) {
      llvm::StringRef name;
      success = names_array->GetItemAtIndexAsString(i, name);
      if (!success) {
        error.SetErrorStringWithFormat(
            "BRFR::CFSD: Malformed element %zu in the names array.", i);
        return nullptr;
      }
      names_set.insert(name);
    }
  }

  return new BreakpointResolverFileRegex(bkpt, regex, names_set, exact_match);
}

StructuredData::ObjectSP
BreakpointResolverFileRegex::SerializeToStructuredData() {
  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());

  options_dict_sp->AddStringItem(GetKey(OptionNames::RegexString),
                                 m_regex.GetText());
  options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch),
                                  m_exact_match);
  if (!m_function_names.empty()) {
    StructuredData::ArraySP names_array_sp(new StructuredData::Array());
    for (std::string name : m_function_names) {
      StructuredData::StringSP item(new StructuredData::String(name));
      names_array_sp->AddItem(item);
    }
    options_dict_sp->AddItem(GetKey(OptionNames::LineNumber), names_array_sp);
  }

  return WrapOptionsDict(options_dict_sp);
}

Searcher::CallbackReturn
BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter,
                                            SymbolContext &context,
                                            Address *addr, bool containing) {

  assert(m_breakpoint != NULL);
  if (!context.target_sp)
    return eCallbackReturnContinue;

  CompileUnit *cu = context.comp_unit;
  FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
  std::vector<uint32_t> line_matches;
  context.target_sp->GetSourceManager().FindLinesMatchingRegex(
      cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);

  uint32_t num_matches = line_matches.size();
  for (uint32_t i = 0; i < num_matches; i++) {
    SymbolContextList sc_list;
    const bool search_inlines = false;

    cu->ResolveSymbolContext(cu_file_spec, line_matches[i], search_inlines,
                             m_exact_match, eSymbolContextEverything, sc_list);
    // Find all the function names:
    if (!m_function_names.empty()) {
      std::vector<size_t> sc_to_remove;
      for (size_t i = 0; i < sc_list.GetSize(); i++) {
        SymbolContext sc_ctx;
        sc_list.GetContextAtIndex(i, sc_ctx);
        std::string name(
            sc_ctx
                .GetFunctionName(
                    Mangled::NamePreference::ePreferDemangledWithoutArguments)
                .AsCString());
        if (!m_function_names.count(name)) {
          sc_to_remove.push_back(i);
        }
      }

      if (!sc_to_remove.empty()) {
        std::vector<size_t>::reverse_iterator iter;
        std::vector<size_t>::reverse_iterator rend = sc_to_remove.rend();
        for (iter = sc_to_remove.rbegin(); iter != rend; iter++) {
          sc_list.RemoveContextAtIndex(*iter);
        }
      }
    }

    const bool skip_prologue = true;

    BreakpointResolver::SetSCMatchesByLine(filter, sc_list, skip_prologue,
                                           m_regex.GetText());
  }
  assert(m_breakpoint != NULL);

  return Searcher::eCallbackReturnContinue;
}

Searcher::Depth BreakpointResolverFileRegex::GetDepth() {
  return Searcher::eDepthCompUnit;
}

void BreakpointResolverFileRegex::GetDescription(Stream *s) {
  s->Printf("source regex = \"%s\", exact_match = %d",
            m_regex.GetText().str().c_str(), m_exact_match);
}

void BreakpointResolverFileRegex::Dump(Stream *s) const {}

lldb::BreakpointResolverSP
BreakpointResolverFileRegex::CopyForBreakpoint(Breakpoint &breakpoint) {
  lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(
      &breakpoint, m_regex, m_function_names, m_exact_match));
  return ret_sp;
}

void BreakpointResolverFileRegex::AddFunctionName(const char *func_name) {
  m_function_names.insert(func_name);
}
