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

// C Includes

// C++ Includes

// Other libraries and framework includes

// Project includes
#include "lldb/DataFormatters/FormatCache.h"

using namespace lldb;
using namespace lldb_private;

FormatCache::Entry::Entry()
    : m_format_cached(false), m_summary_cached(false),
      m_synthetic_cached(false), m_validator_cached(false), m_format_sp(),
      m_summary_sp(), m_synthetic_sp(), m_validator_sp() {}

FormatCache::Entry::Entry(lldb::TypeFormatImplSP format_sp)
    : m_summary_cached(false), m_synthetic_cached(false),
      m_validator_cached(false), m_summary_sp(), m_synthetic_sp(),
      m_validator_sp() {
  SetFormat(format_sp);
}

FormatCache::Entry::Entry(lldb::TypeSummaryImplSP summary_sp)
    : m_format_cached(false), m_synthetic_cached(false),
      m_validator_cached(false), m_format_sp(), m_synthetic_sp(),
      m_validator_sp() {
  SetSummary(summary_sp);
}

FormatCache::Entry::Entry(lldb::SyntheticChildrenSP synthetic_sp)
    : m_format_cached(false), m_summary_cached(false),
      m_validator_cached(false), m_format_sp(), m_summary_sp(),
      m_validator_sp() {
  SetSynthetic(synthetic_sp);
}

FormatCache::Entry::Entry(lldb::TypeValidatorImplSP validator_sp)
    : m_format_cached(false), m_summary_cached(false),
      m_synthetic_cached(false), m_format_sp(), m_summary_sp(),
      m_synthetic_sp() {
  SetValidator(validator_sp);
}

FormatCache::Entry::Entry(lldb::TypeFormatImplSP format_sp,
                          lldb::TypeSummaryImplSP summary_sp,
                          lldb::SyntheticChildrenSP synthetic_sp,
                          lldb::TypeValidatorImplSP validator_sp) {
  SetFormat(format_sp);
  SetSummary(summary_sp);
  SetSynthetic(synthetic_sp);
  SetValidator(validator_sp);
}

bool FormatCache::Entry::IsFormatCached() { return m_format_cached; }

bool FormatCache::Entry::IsSummaryCached() { return m_summary_cached; }

bool FormatCache::Entry::IsSyntheticCached() { return m_synthetic_cached; }

bool FormatCache::Entry::IsValidatorCached() { return m_validator_cached; }

lldb::TypeFormatImplSP FormatCache::Entry::GetFormat() { return m_format_sp; }

lldb::TypeSummaryImplSP FormatCache::Entry::GetSummary() {
  return m_summary_sp;
}

lldb::SyntheticChildrenSP FormatCache::Entry::GetSynthetic() {
  return m_synthetic_sp;
}

lldb::TypeValidatorImplSP FormatCache::Entry::GetValidator() {
  return m_validator_sp;
}

void FormatCache::Entry::SetFormat(lldb::TypeFormatImplSP format_sp) {
  m_format_cached = true;
  m_format_sp = format_sp;
}

void FormatCache::Entry::SetSummary(lldb::TypeSummaryImplSP summary_sp) {
  m_summary_cached = true;
  m_summary_sp = summary_sp;
}

void FormatCache::Entry::SetSynthetic(lldb::SyntheticChildrenSP synthetic_sp) {
  m_synthetic_cached = true;
  m_synthetic_sp = synthetic_sp;
}

void FormatCache::Entry::SetValidator(lldb::TypeValidatorImplSP validator_sp) {
  m_validator_cached = true;
  m_validator_sp = validator_sp;
}

FormatCache::FormatCache()
    : m_map(), m_mutex()
#ifdef LLDB_CONFIGURATION_DEBUG
      ,
      m_cache_hits(0), m_cache_misses(0)
#endif
{
}

FormatCache::Entry &FormatCache::GetEntry(const ConstString &type) {
  auto i = m_map.find(type), e = m_map.end();
  if (i != e)
    return i->second;
  m_map[type] = FormatCache::Entry();
  return m_map[type];
}

bool FormatCache::GetFormat(const ConstString &type,
                            lldb::TypeFormatImplSP &format_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  auto entry = GetEntry(type);
  if (entry.IsFormatCached()) {
#ifdef LLDB_CONFIGURATION_DEBUG
    m_cache_hits++;
#endif
    format_sp = entry.GetFormat();
    return true;
  }
#ifdef LLDB_CONFIGURATION_DEBUG
  m_cache_misses++;
#endif
  format_sp.reset();
  return false;
}

bool FormatCache::GetSummary(const ConstString &type,
                             lldb::TypeSummaryImplSP &summary_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  auto entry = GetEntry(type);
  if (entry.IsSummaryCached()) {
#ifdef LLDB_CONFIGURATION_DEBUG
    m_cache_hits++;
#endif
    summary_sp = entry.GetSummary();
    return true;
  }
#ifdef LLDB_CONFIGURATION_DEBUG
  m_cache_misses++;
#endif
  summary_sp.reset();
  return false;
}

bool FormatCache::GetSynthetic(const ConstString &type,
                               lldb::SyntheticChildrenSP &synthetic_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  auto entry = GetEntry(type);
  if (entry.IsSyntheticCached()) {
#ifdef LLDB_CONFIGURATION_DEBUG
    m_cache_hits++;
#endif
    synthetic_sp = entry.GetSynthetic();
    return true;
  }
#ifdef LLDB_CONFIGURATION_DEBUG
  m_cache_misses++;
#endif
  synthetic_sp.reset();
  return false;
}

bool FormatCache::GetValidator(const ConstString &type,
                               lldb::TypeValidatorImplSP &validator_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  auto entry = GetEntry(type);
  if (entry.IsValidatorCached()) {
#ifdef LLDB_CONFIGURATION_DEBUG
    m_cache_hits++;
#endif
    validator_sp = entry.GetValidator();
    return true;
  }
#ifdef LLDB_CONFIGURATION_DEBUG
  m_cache_misses++;
#endif
  validator_sp.reset();
  return false;
}

void FormatCache::SetFormat(const ConstString &type,
                            lldb::TypeFormatImplSP &format_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  GetEntry(type).SetFormat(format_sp);
}

void FormatCache::SetSummary(const ConstString &type,
                             lldb::TypeSummaryImplSP &summary_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  GetEntry(type).SetSummary(summary_sp);
}

void FormatCache::SetSynthetic(const ConstString &type,
                               lldb::SyntheticChildrenSP &synthetic_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  GetEntry(type).SetSynthetic(synthetic_sp);
}

void FormatCache::SetValidator(const ConstString &type,
                               lldb::TypeValidatorImplSP &validator_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  GetEntry(type).SetValidator(validator_sp);
}

void FormatCache::Clear() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  m_map.clear();
}
