// 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_;
};
}

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
