// 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 "util/parse_number.h"

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

#include "util/hex_float.h"

namespace spvutils {

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<spvutils::Float16>> hVal(0);
      if (!ParseNumber(text, &hVal)) {
        ErrorMsgStream(error_msg) << "Invalid 16-bit float literal: " << text;
        return EncodeNumberStatus::kInvalidText;
      }
      // getAsFloat will return the spvutils::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 spvutils
