//===-- TypeFormat.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/TypeFormat.h"




#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"

#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb;
using namespace lldb_private;

TypeFormatImpl::TypeFormatImpl(const Flags &flags)
    : m_flags(flags), m_my_revision(0) {}

TypeFormatImpl::~TypeFormatImpl() {}

TypeFormatImpl_Format::TypeFormatImpl_Format(lldb::Format f,
                                             const TypeFormatImpl::Flags &flags)
    : TypeFormatImpl(flags), m_format(f) {}

TypeFormatImpl_Format::~TypeFormatImpl_Format() {}

bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
                                         std::string &dest) const {
  if (!valobj)
    return false;
  if (valobj->CanProvideValue()) {
    Value &value(valobj->GetValue());
    const Value::ContextType context_type = value.GetContextType();
    ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
    DataExtractor data;

    if (context_type == Value::eContextTypeRegisterInfo) {
      const RegisterInfo *reg_info = value.GetRegisterInfo();
      if (reg_info) {
        Status error;
        valobj->GetData(data, error);
        if (error.Fail())
          return false;

        StreamString reg_sstr;
        DumpDataExtractor(data, &reg_sstr, 0, GetFormat(), reg_info->byte_size,
                          1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0,
                          exe_ctx.GetBestExecutionContextScope());
        dest = std::string(reg_sstr.GetString());
      }
    } else {
      CompilerType compiler_type = value.GetCompilerType();
      if (compiler_type) {
        // put custom bytes to display in the DataExtractor to override the
        // default value logic
        if (GetFormat() == eFormatCString) {
          lldb_private::Flags type_flags(compiler_type.GetTypeInfo(
              nullptr)); // disambiguate w.r.t. TypeFormatImpl::Flags
          if (type_flags.Test(eTypeIsPointer) &&
              !type_flags.Test(eTypeIsObjC)) {
            // if we are dumping a pointer as a c-string, get the pointee data
            // as a string
            TargetSP target_sp(valobj->GetTargetSP());
            if (target_sp) {
              size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
              Status error;
              DataBufferSP buffer_sp(new DataBufferHeap(max_len + 1, 0));
              Address address(valobj->GetPointerValue());
              if (target_sp->ReadCStringFromMemory(
                      address, (char *)buffer_sp->GetBytes(), max_len, error) &&
                  error.Success())
                data.SetData(buffer_sp);
            }
          }
        } else {
          Status error;
          valobj->GetData(data, error);
          if (error.Fail())
            return false;
        }

        ExecutionContextScope *exe_scope =
            exe_ctx.GetBestExecutionContextScope();
        llvm::Optional<uint64_t> size = compiler_type.GetByteSize(exe_scope);
        if (!size)
          return false;
        StreamString sstr;
        compiler_type.DumpTypeValue(
            &sstr,                          // The stream to use for display
            GetFormat(),                    // Format to display this type with
            data,                           // Data to extract from
            0,                              // Byte offset into "m_data"
            *size,                          // Byte size of item in "m_data"
            valobj->GetBitfieldBitSize(),   // Bitfield bit size
            valobj->GetBitfieldBitOffset(), // Bitfield bit offset
            exe_scope);
        // Given that we do not want to set the ValueObject's m_error for a
        // formatting error (or else we wouldn't be able to reformat until a
        // next update), an empty string is treated as a "false" return from
        // here, but that's about as severe as we get
        // CompilerType::DumpTypeValue() should always return something, even
        // if that something is an error message
        dest = std::string(sstr.GetString());
      }
    }
    return !dest.empty();
  } else
    return false;
}

std::string TypeFormatImpl_Format::GetDescription() {
  StreamString sstr;
  sstr.Printf("%s%s%s%s", FormatManager::GetFormatAsCString(GetFormat()),
              Cascades() ? "" : " (not cascading)",
              SkipsPointers() ? " (skip pointers)" : "",
              SkipsReferences() ? " (skip references)" : "");
  return std::string(sstr.GetString());
}

TypeFormatImpl_EnumType::TypeFormatImpl_EnumType(
    ConstString type_name, const TypeFormatImpl::Flags &flags)
    : TypeFormatImpl(flags), m_enum_type(type_name), m_types() {}

TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() {}

bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
                                           std::string &dest) const {
  dest.clear();
  if (!valobj)
    return false;
  if (!valobj->CanProvideValue())
    return false;
  ProcessSP process_sp;
  TargetSP target_sp;
  void *valobj_key = (process_sp = valobj->GetProcessSP()).get();
  if (!valobj_key)
    valobj_key = (target_sp = valobj->GetTargetSP()).get();
  else
    target_sp = process_sp->GetTarget().shared_from_this();
  if (!valobj_key)
    return false;
  auto iter = m_types.find(valobj_key), end = m_types.end();
  CompilerType valobj_enum_type;
  if (iter == end) {
    // probably a redundant check
    if (!target_sp)
      return false;
    const ModuleList &images(target_sp->GetImages());
    TypeList types;
    llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
    images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX,
                     searched_symbol_files, types);
    if (types.Empty())
      return false;
    for (lldb::TypeSP type_sp : types.Types()) {
      if (!type_sp)
        continue;
      if ((type_sp->GetForwardCompilerType().GetTypeInfo() &
           eTypeIsEnumeration) == eTypeIsEnumeration) {
        valobj_enum_type = type_sp->GetFullCompilerType();
        m_types.emplace(valobj_key, valobj_enum_type);
        break;
      }
    }
  } else
    valobj_enum_type = iter->second;
  if (!valobj_enum_type.IsValid())
    return false;
  DataExtractor data;
  Status error;
  valobj->GetData(data, error);
  if (error.Fail())
    return false;
  ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
  StreamString sstr;
  valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0,
                                 data.GetByteSize(), 0, 0,
                                 exe_ctx.GetBestExecutionContextScope());
  if (!sstr.GetString().empty())
    dest = std::string(sstr.GetString());
  return !dest.empty();
}

std::string TypeFormatImpl_EnumType::GetDescription() {
  StreamString sstr;
  sstr.Printf("as type %s%s%s%s", m_enum_type.AsCString("<invalid type>"),
              Cascades() ? "" : " (not cascading)",
              SkipsPointers() ? " (skip pointers)" : "",
              SkipsReferences() ? " (skip references)" : "");
  return std::string(sstr.GetString());
}
