// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "garnet/bin/zxdb/expr/cast.h"

#include "garnet/bin/zxdb/common/err.h"
#include "garnet/bin/zxdb/expr/expr_value.h"
#include "garnet/bin/zxdb/expr/type_parser.h"
#include "garnet/bin/zxdb/symbols/base_type.h"
#include "garnet/bin/zxdb/symbols/modified_type.h"

namespace zxdb {

namespace {

// Returns true if this type is enough like an integer to support conversion
// to another number type. This includes all base types except floating point.
bool IsIntegerLike(const Type* t) {
  // Pointers count.
  if (const ModifiedType* modified_type = t->AsModifiedType())
    return modified_type->tag() == DwarfTag::kPointerType;

  const BaseType* base_type = t->AsBaseType();
  if (!base_type)
    return false;

  int kind = base_type->base_type();
  return kind == BaseType::kBaseTypeAddress ||
         kind == BaseType::kBaseTypeBoolean ||
         kind == BaseType::kBaseTypeSigned ||
         kind == BaseType::kBaseTypeSignedChar ||
         kind == BaseType::kBaseTypeUnsigned ||
         kind == BaseType::kBaseTypeUnsignedChar ||
         kind == BaseType::kBaseTypeUTF;
}

bool IsSignedBaseType(const Type* type) {
  const BaseType* base_type = type->AsBaseType();
  if (!base_type)
    return false;
  int kind = base_type->base_type();
  return kind == BaseType::kBaseTypeSigned ||
         kind == BaseType::kBaseTypeSignedChar;
}

bool IsBooleanBaseType(const Type* type) {
  const BaseType* base_type = type->AsBaseType();
  if (!base_type)
    return false;
  return base_type->base_type() == BaseType::kBaseTypeBoolean;
}

bool IsFloatingPointBaseType(const Type* type) {
  const BaseType* base_type = type->AsBaseType();
  if (!base_type)
    return false;
  return base_type->base_type() == BaseType::kBaseTypeFloat;
}

// Numbers include integers and floating point.
bool IsNumberLike(const Type* t) {
  return IsIntegerLike(t) || IsFloatingPointBaseType(t);
}

// Creates an ExprValue with the contents of the given "value". The size of
// "value" must match the destination type. This function always places the
// output into *result and returns an empty Err() for the convenience of the
// callers.
template <typename T>
Err CreateValue(T value, const fxl::RefPtr<Type>& dest_type,
                const ExprValueSource& dest_source, ExprValue* result) {
  FXL_DCHECK(sizeof(T) == dest_type->byte_size());

  std::vector<uint8_t> dest_bytes;
  dest_bytes.resize(sizeof(T));
  memcpy(&dest_bytes[0], &value, sizeof(T));

  *result = ExprValue(dest_type, std::move(dest_bytes), dest_source);
  return Err();
}

std::vector<uint8_t> CastToIntegerOfSize(const std::vector<uint8_t>& source,
                                         bool source_is_signed,
                                         size_t dest_size) {
  if (source.size() > dest_size) {
    // Truncate. Assume little-endian so copy from the beginning to get the low
    // bits.
    return std::vector<uint8_t>(source.begin(), source.begin() + dest_size);
  } else if (source.size() < dest_size) {
    // Extend.
    std::vector<uint8_t> result = source;
    if (source_is_signed && result.back() & 0b10000000) {
      // Sign-extend.
      result.resize(dest_size, 0xff);
    } else {
      // 0-extend.
      result.resize(dest_size);
    }
    return result;
  }
  return source;  // No change.
}

// The "Int64" parameter is either "uint64_t" or "int64_t" depending on the
// signedness of the integer desired.
template <typename Int64>
ExprValue CastFloatToIntT(double double_value,
                          const fxl::RefPtr<Type>& dest_type,
                          const ExprValueSource& dest_source) {
  Int64 int64_value = static_cast<Int64>(double_value);

  std::vector<uint8_t> int64_data;
  int64_data.resize(sizeof(Int64));
  memcpy(&int64_data[0], &int64_value, sizeof(Int64));

  // CastToIntegerOfSize will downcast the int64 to the desired result size.
  return ExprValue(
      dest_type, CastToIntegerOfSize(int64_data, true, dest_type->byte_size()),
      dest_source);
}

Err CastFloatToInt(const ExprValue& source, const fxl::RefPtr<Type>& dest_type,
                   const Type* concrete_dest_type,
                   const ExprValueSource& dest_source, ExprValue* result) {
  double source_value;
  Err err = source.PromoteToDouble(&source_value);
  if (err.has_error())
    return err;

  if (IsSignedBaseType(concrete_dest_type)) {
    *result = CastFloatToIntT<int64_t>(source_value, dest_type, dest_source);
    return Err();
  } else {
    *result = CastFloatToIntT<uint64_t>(source_value, dest_type, dest_source);
    return Err();
  }
  return Err("Can't convert a floating-point of size %u to an integer.",
             source.type()->byte_size());
}

// Converts an integer value into to a binary representation of a float/double.
// The "Int" template type should be a [u]int64_t of the signedness of the
// source type, and the "Float" type is the output type required.
template <typename Int, typename Float>
Err CastIntToFloatT(const ExprValue& source, const fxl::RefPtr<Type>& dest_type,
                    const ExprValueSource& dest_source, ExprValue* result) {
  // Get the integer out as a 64-bit value of the correct sign.
  Int source_int;
  Err err = source.PromoteTo64(&source_int);
  if (err.has_error())
    return err;

  return CreateValue(static_cast<Float>(source_int), dest_type, dest_source,
                     result);
}

Err CastIntToFloat(const ExprValue& source, bool source_is_signed,
                   const fxl::RefPtr<Type>& dest_type,
                   const ExprValueSource& dest_source, ExprValue* result) {
  if (source_is_signed) {
    if (dest_type->byte_size() == 4) {
      return CastIntToFloatT<int64_t, float>(source, dest_type, dest_source,
                                             result);
    } else if (dest_type->byte_size() == 8) {
      return CastIntToFloatT<int64_t, double>(source, dest_type, dest_source,
                                              result);
    }
  } else {
    if (dest_type->byte_size() == 4) {
      return CastIntToFloatT<uint64_t, float>(source, dest_type, dest_source,
                                              result);
    } else if (dest_type->byte_size() == 8) {
      return CastIntToFloatT<uint64_t, double>(source, dest_type, dest_source,
                                               result);
    }
  }

  return Err("Can't convert to floating-point number of size %u.",
             dest_type->byte_size());
}

Err CastFloatToFloat(const ExprValue& source,
                     const fxl::RefPtr<Type>& dest_type,
                     const ExprValueSource& dest_source, ExprValue* result) {
  if (source.data().size() == 4) {
    float f = source.GetAs<float>();
    if (dest_type->byte_size() == 4)
      return CreateValue<float>(f, dest_type, dest_source, result);
    else if (dest_type->byte_size() == 8)
      return CreateValue<double>(f, dest_type, dest_source, result);
  } else if (source.data().size() == 8) {
    double d = source.GetAs<double>();
    if (dest_type->byte_size() == 4)
      return CreateValue<float>(d, dest_type, dest_source, result);
    else if (dest_type->byte_size() == 8)
      return CreateValue<double>(d, dest_type, dest_source, result);
  }

  return Err("Can't convert floating-point from size %zu to %u.",
             source.data().size(), dest_type->byte_size());
}

Err CastNumberToBool(const ExprValue& source, const Type* concrete_from,
                     const fxl::RefPtr<Type>& dest_type,
                     const ExprValueSource& dest_source, ExprValue* result) {
  bool value = false;

  if (IsIntegerLike(concrete_from)) {
    // All integer-like sources just look for non-zero bytes.
    for (uint8_t cur : source.data()) {
      if (cur) {
        value = true;
        break;
      }
    }
  } else {
    // floating-point-like sources which can't do a byte-by-byte comparison.
    FXL_DCHECK(IsFloatingPointBaseType(concrete_from));
    double double_value;
    Err err = source.PromoteToDouble(&double_value);
    if (err.has_error())
      return err;

    // Use C++ casting rules to convert to bool.
    value = !!double_value;
  }

  // The data buffer that will be returned, matching the size of the boolean.
  std::vector<uint8_t> dest_data;
  dest_data.resize(dest_type->byte_size());
  if (value)
    dest_data[0] = 1;

  *result = ExprValue(dest_type, std::move(dest_data), dest_source);
  return Err();
}

// Returns true if the two concrete types (as a result of calling
// Type::GetConcreteType()) can be coerced by copying the data. This includes
// things that are actually the same, as well as things like signed/unsigned
// conversions and pointer/int conversions that our very loose coercion rules
// support.
bool TypesAreBinaryCoercable(const Type* a, const Type* b) {
  // TODO(brettw) need to handle bit fields.
  if (a->byte_size() != b->byte_size())
    return false;  // Sizes must match or copying definitely won't work.

  // It's possible for things to have the same type but different Type objects
  // depending on how the types were arrived at and whether the source and dest
  // are from the same compilation unit. Assume if the string names of the
  // types match as well as the size, it's the same type.
  if (a->GetFullName() == b->GetFullName())
    return true;  // Names match, assume same type.

  // Allow all integers and pointers of the same size to be converted by
  // copying.
  return IsIntegerLike(a) && IsIntegerLike(b);
}

}  // namespace

Err CoerceValueTo(const ExprValue& source, const fxl::RefPtr<Type>& dest_type,
                  const ExprValueSource& dest_source, ExprValue* result) {
  // There are several fundamental types of things that can be casted:
  //  - Aggregate types: Can only convert if they're the same.
  //  - Integers and integer-like things: This includes pointers.
  //  - Floating-point numbers.
  //  - Booleans.

  // Prevent crashes if we get bad types with no size.
  if (source.data().size() == 0 || dest_type->byte_size() == 0)
    return Err("Type has 0 size.");

  // Get the types without "const", etc. modifiers.
  const Type* concrete_from = source.type()->GetConcreteType();
  const Type* concrete_to = dest_type->GetConcreteType();

  // Handles identical type conversions. This includes all aggregate types.
  if (TypesAreBinaryCoercable(concrete_from, concrete_to)) {
    *result = ExprValue(dest_type, source.data(), dest_source);
    return Err();
  }

  // Conversions to bool. Conversions from bool will follow the standard
  // "number to X" path where we assume the bool is like a number.
  if (IsBooleanBaseType(concrete_to) && IsNumberLike(concrete_from)) {
    return CastNumberToBool(source, concrete_from, dest_type, dest_source,
                            result);
  }

  // Conversions between different types of ints (truncate or extend).
  if (IsIntegerLike(concrete_from) && IsIntegerLike(concrete_to)) {
    *result = ExprValue(
        dest_type,
        CastToIntegerOfSize(source.data(), IsSignedBaseType(concrete_from),
                            concrete_to->byte_size()),
        dest_source);
    return Err();
  }

  // Conversions between different types of floats.
  if (IsFloatingPointBaseType(concrete_from) &&
      IsFloatingPointBaseType(concrete_to))
    return CastFloatToFloat(source, dest_type, dest_source, result);

  // Conversions between ints and floats.
  if (IsIntegerLike(concrete_to) && IsFloatingPointBaseType(concrete_from))
    return CastFloatToInt(source, dest_type, concrete_to, dest_source, result);
  if (IsFloatingPointBaseType(concrete_to) && IsIntegerLike(concrete_from)) {
    return CastIntToFloat(source, IsSignedBaseType(concrete_from), dest_type,
                          dest_source, result);
  }

  return Err("Can't cast from '%s' to '%s'.",
             source.type()->GetFullName().c_str(),
             dest_type->GetFullName().c_str());
}

Err ReinterpretCast(const ExprValue& source, const fxl::RefPtr<Type>& dest_type,
                    ExprValue* result) {
  if (!source.type())
    return Err("Can't cast from a null type.");
  if (!dest_type)
    return Err("Can't cast to a null type.");

  // The input and output types should both be integer-like (this includes
  // pointers). This check is more restrictive than the "coerce" rules above
  // because we don't want to support things like integer-to-double conversion.
  const Type* concrete_source = source.type()->GetConcreteType();
  if (!IsIntegerLike(concrete_source)) {
    return Err("Can't cast from a '%s'.", source.type()->GetFullName().c_str());
  }

  const Type* concrete_dest = dest_type->GetConcreteType();
  if (!IsIntegerLike(concrete_dest))
    return Err("Can't cast to a '%s'.", dest_type->GetFullName().c_str());

  // Our implementation of reinterpret_cast is just a bit cast with truncation
  // or 0-fill (not sign extend). C++ would require the type sizes match and
  // would prohibit most number-to-number conversions, but those restrictions
  // aren't useful or even desirable in the case of a debugger handling user
  // input.
  auto new_data = source.data();
  new_data.resize(dest_type->byte_size());
  // The new ExprValueSource severs the tie to the original data since
  // reinterpret_cast "returns" a temporary rather than a reference.
  *result = ExprValue(dest_type, std::move(new_data), ExprValueSource());
  return Err();
}

Err ReinterpretCast(const ExprValue& source, const std::string& dest_type_str,
                    ExprValue* result) {
  fxl::RefPtr<Type> dest_type;
  Err err = StringToType(dest_type_str, &dest_type);
  if (err.has_error())
    return err;
  return ReinterpretCast(source, dest_type, result);
}

}  // namespace zxdb
