// Copyright (c) 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/util/parse_number.h"

#include <functional>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
#include <tuple>

#include "source/util/hex_float.h"

namespace spvtools {
namespace utils {
namespace {

// A helper class that temporarily stores error messages and dump the messages
// to a string which given as as pointer when it is destructed. If the given
// pointer is a nullptr, this class does not store error message.
class ErrorMsgStream {
 public:
  explicit ErrorMsgStream(std::string* error_msg_sink)
      : error_msg_sink_(error_msg_sink) {
    if (error_msg_sink_) stream_.reset(new std::ostringstream());
  }
  ~ErrorMsgStream() {
    if (error_msg_sink_ && stream_) *error_msg_sink_ = stream_->str();
  }
  template <typename T>
  ErrorMsgStream& operator<<(T val) {
    if (stream_) *stream_ << val;
    return *this;
  }

 private:
  std::unique_ptr<std::ostringstream> stream_;
  // The destination string to which this class dump the error message when
  // destructor is called.
  std::string* error_msg_sink_;
};
}  // namespace

EncodeNumberStatus ParseAndEncodeIntegerNumber(
    const char* text, const NumberType& type,
    std::function<void(uint32_t)> emit, std::string* error_msg) {
  if (!text) {
    ErrorMsgStream(error_msg) << "The given text is a nullptr";
    return EncodeNumberStatus::kInvalidText;
  }

  if (!IsIntegral(type)) {
    ErrorMsgStream(error_msg) << "The expected type is not a integer type";
    return EncodeNumberStatus::kInvalidUsage;
  }

  const uint32_t bit_width = AssumedBitWidth(type);

  if (bit_width > 64) {
    ErrorMsgStream(error_msg)
        << "Unsupported " << bit_width << "-bit integer literals";
    return EncodeNumberStatus::kUnsupported;
  }

  // Either we are expecting anything or integer.
  bool is_negative = text[0] == '-';
  bool can_be_signed = IsSigned(type);

  if (is_negative && !can_be_signed) {
    ErrorMsgStream(error_msg)
        << "Cannot put a negative number in an unsigned literal";
    return EncodeNumberStatus::kInvalidUsage;
  }

  const bool is_hex = text[0] == '0' && (text[1] == 'x' || text[1] == 'X');

  uint64_t decoded_bits;
  if (is_negative) {
    int64_t decoded_signed = 0;

    if (!ParseNumber(text, &decoded_signed)) {
      ErrorMsgStream(error_msg) << "Invalid signed integer literal: " << text;
      return EncodeNumberStatus::kInvalidText;
    }

    if (!CheckRangeAndIfHexThenSignExtend(decoded_signed, type, is_hex,
                                          &decoded_signed)) {
      ErrorMsgStream(error_msg)
          << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase
          << decoded_signed << " does not fit in a " << std::dec << bit_width
          << "-bit " << (IsSigned(type) ? "signed" : "unsigned") << " integer";
      return EncodeNumberStatus::kInvalidText;
    }
    decoded_bits = decoded_signed;
  } else {
    // There's no leading minus sign, so parse it as an unsigned integer.
    if (!ParseNumber(text, &decoded_bits)) {
      ErrorMsgStream(error_msg) << "Invalid unsigned integer literal: " << text;
      return EncodeNumberStatus::kInvalidText;
    }
    if (!CheckRangeAndIfHexThenSignExtend(decoded_bits, type, is_hex,
                                          &decoded_bits)) {
      ErrorMsgStream(error_msg)
          << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase
          << decoded_bits << " does not fit in a " << std::dec << bit_width
          << "-bit " << (IsSigned(type) ? "signed" : "unsigned") << " integer";
      return EncodeNumberStatus::kInvalidText;
    }
  }
  if (bit_width > 32) {
    uint32_t low = uint32_t(0x00000000ffffffff & decoded_bits);
    uint32_t high = uint32_t((0xffffffff00000000 & decoded_bits) >> 32);
    emit(low);
    emit(high);
  } else {
    emit(uint32_t(decoded_bits));
  }
  return EncodeNumberStatus::kSuccess;
}

EncodeNumberStatus ParseAndEncodeFloatingPointNumber(
    const char* text, const NumberType& type,
    std::function<void(uint32_t)> emit, std::string* error_msg) {
  if (!text) {
    ErrorMsgStream(error_msg) << "The given text is a nullptr";
    return EncodeNumberStatus::kInvalidText;
  }

  if (!IsFloating(type)) {
    ErrorMsgStream(error_msg) << "The expected type is not a float type";
    return EncodeNumberStatus::kInvalidUsage;
  }

  const auto bit_width = AssumedBitWidth(type);
  switch (bit_width) {
    case 16: {
      HexFloat<FloatProxy<Float16>> hVal(0);
      if (!ParseNumber(text, &hVal)) {
        ErrorMsgStream(error_msg) << "Invalid 16-bit float literal: " << text;
        return EncodeNumberStatus::kInvalidText;
      }
      // getAsFloat will return the Float16 value, and get_value
      // will return a uint16_t representing the bits of the float.
      // The encoding is therefore correct from the perspective of the SPIR-V
      // spec since the top 16 bits will be 0.
      emit(static_cast<uint32_t>(hVal.value().getAsFloat().get_value()));
      return EncodeNumberStatus::kSuccess;
    } break;
    case 32: {
      HexFloat<FloatProxy<float>> fVal(0.0f);
      if (!ParseNumber(text, &fVal)) {
        ErrorMsgStream(error_msg) << "Invalid 32-bit float literal: " << text;
        return EncodeNumberStatus::kInvalidText;
      }
      emit(BitwiseCast<uint32_t>(fVal));
      return EncodeNumberStatus::kSuccess;
    } break;
    case 64: {
      HexFloat<FloatProxy<double>> dVal(0.0);
      if (!ParseNumber(text, &dVal)) {
        ErrorMsgStream(error_msg) << "Invalid 64-bit float literal: " << text;
        return EncodeNumberStatus::kInvalidText;
      }
      uint64_t decoded_val = BitwiseCast<uint64_t>(dVal);
      uint32_t low = uint32_t(0x00000000ffffffff & decoded_val);
      uint32_t high = uint32_t((0xffffffff00000000 & decoded_val) >> 32);
      emit(low);
      emit(high);
      return EncodeNumberStatus::kSuccess;
    } break;
    default:
      break;
  }
  ErrorMsgStream(error_msg)
      << "Unsupported " << bit_width << "-bit float literals";
  return EncodeNumberStatus::kUnsupported;
}

EncodeNumberStatus ParseAndEncodeNumber(const char* text,
                                        const NumberType& type,
                                        std::function<void(uint32_t)> emit,
                                        std::string* error_msg) {
  if (!text) {
    ErrorMsgStream(error_msg) << "The given text is a nullptr";
    return EncodeNumberStatus::kInvalidText;
  }

  if (IsUnknown(type)) {
    ErrorMsgStream(error_msg)
        << "The expected type is not a integer or float type";
    return EncodeNumberStatus::kInvalidUsage;
  }

  // If we explicitly expect a floating-point number, we should handle that
  // first.
  if (IsFloating(type)) {
    return ParseAndEncodeFloatingPointNumber(text, type, emit, error_msg);
  }

  return ParseAndEncodeIntegerNumber(text, type, emit, error_msg);
}

}  // namespace utils
}  // namespace spvtools
