// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/double_conversion.h"

#include "third_party/double-conversion/src/double-conversion.h"

#include "vm/exceptions.h"
#include "vm/globals.h"
#include "vm/object.h"

namespace dart {

char const DoubleToStringConstants::kExponentChar = 'e';
const char* const DoubleToStringConstants::kInfinitySymbol = "Infinity";
const char* const DoubleToStringConstants::kNaNSymbol = "NaN";

void DoubleToCString(double d, char* buffer, int buffer_size) {
  static const int kDecimalLow = -6;
  static const int kDecimalHigh = 21;

  // The output contains the sign, at most kDecimalHigh - 1 digits,
  // the decimal point followed by a 0 plus the \0.
  ASSERT(buffer_size >= 1 + (kDecimalHigh - 1) + 1 + 1 + 1);
  // Or it contains the sign, a 0, the decimal point, kDecimalLow '0's,
  // 17 digits (the precision needed for doubles), plus the \0.
  ASSERT(buffer_size >= 1 + 1 + 1 + kDecimalLow + 17 + 1);
  // Alternatively it contains a sign, at most 17 digits (precision needed for
  // any double), the decimal point, the exponent character, the exponent's
  // sign, at most three exponent digits, plus the \0.
  ASSERT(buffer_size >= 1 + 17 + 1 + 1 + 1 + 3 + 1);

  static const int kConversionFlags =
      double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
      double_conversion::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |
      double_conversion::DoubleToStringConverter::
          EMIT_TRAILING_ZERO_AFTER_POINT;

  const double_conversion::DoubleToStringConverter converter(
      kConversionFlags, DoubleToStringConstants::kInfinitySymbol,
      DoubleToStringConstants::kNaNSymbol,
      DoubleToStringConstants::kExponentChar, kDecimalLow, kDecimalHigh, 0,
      0);  // Last two values are ignored in shortest mode.

  double_conversion::StringBuilder builder(buffer, buffer_size);
  bool status = converter.ToShortest(d, &builder);
  ASSERT(status);
  char* result = builder.Finalize();
  ASSERT(result == buffer);
}

StringPtr DoubleToStringAsFixed(double d, int fraction_digits) {
  static const int kMinFractionDigits = 0;
  static const int kMaxFractionDigits = 20;
  static const int kMaxDigitsBeforePoint = 20;
  // The boundaries are exclusive.
  static const double kLowerBoundary = -1e21;
  static const double kUpperBoundary = 1e21;
  // TODO(floitsch): remove the UNIQUE_ZERO flag when the test is updated.
  static const int kConversionFlags =
      double_conversion::DoubleToStringConverter::NO_FLAGS;
  const int kBufferSize = 128;

  USE(kMaxDigitsBeforePoint);
  USE(kMaxFractionDigits);
  USE(kLowerBoundary);
  USE(kUpperBoundary);
  USE(kMinFractionDigits);
  USE(kMaxFractionDigits);
  // The output contains the sign, at most kMaxDigitsBeforePoint digits,
  // the decimal point followed by at most fraction_digits digits plus the \0.
  ASSERT(kBufferSize >= 1 + kMaxDigitsBeforePoint + 1 + kMaxFractionDigits + 1);

  ASSERT(kLowerBoundary < d && d < kUpperBoundary);

  ASSERT(kMinFractionDigits <= fraction_digits &&
         fraction_digits <= kMaxFractionDigits);

  const double_conversion::DoubleToStringConverter converter(
      kConversionFlags, DoubleToStringConstants::kInfinitySymbol,
      DoubleToStringConstants::kNaNSymbol,
      DoubleToStringConstants::kExponentChar, 0, 0, 0,
      0);  // Last four values are ignored in fixed mode.

  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
  buffer[kBufferSize - 1] = '\0';
  double_conversion::StringBuilder builder(buffer, kBufferSize);
  bool status = converter.ToFixed(d, fraction_digits, &builder);
  ASSERT(status);
  return String::New(builder.Finalize());
}

StringPtr DoubleToStringAsExponential(double d, int fraction_digits) {
  static const int kMinFractionDigits = -1;  // -1 represents shortest mode.
  static const int kMaxFractionDigits = 20;
  static const int kConversionFlags =
      double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
  const int kBufferSize = 128;

  USE(kMinFractionDigits);
  USE(kMaxFractionDigits);
  // The output contains the sign, at most 1 digits, the decimal point followed
  // by at most kMaxFractionDigits digits, the exponent-character, the
  // exponent-sign and three exponent digits plus \0.
  ASSERT(kBufferSize >= 1 + 1 + kMaxFractionDigits + 1 + 1 + 3 + 1);

  ASSERT(kMinFractionDigits <= fraction_digits &&
         fraction_digits <= kMaxFractionDigits);

  const double_conversion::DoubleToStringConverter converter(
      kConversionFlags, DoubleToStringConstants::kInfinitySymbol,
      DoubleToStringConstants::kNaNSymbol,
      DoubleToStringConstants::kExponentChar, 0, 0, 0,
      0);  // Last four values are ignored in exponential mode.

  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
  buffer[kBufferSize - 1] = '\0';
  double_conversion::StringBuilder builder(buffer, kBufferSize);
  bool status = converter.ToExponential(d, fraction_digits, &builder);
  ASSERT(status);
  return String::New(builder.Finalize());
}

StringPtr DoubleToStringAsPrecision(double d, int precision) {
  static const int kMinPrecisionDigits = 1;
  static const int kMaxPrecisionDigits = 21;
  static const int kMaxLeadingPaddingZeroes = 6;
  static const int kMaxTrailingPaddingZeroes = 0;
  static const int kConversionFlags =
      double_conversion::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
  const int kBufferSize = 128;

  USE(kMinPrecisionDigits);
  USE(kMaxPrecisionDigits);
  // The output contains the sign, a potential leading 0, the decimal point,
  // at most kMax{Leading|Trailing} padding zeroes, precision digits,
  // the exponent-character, the exponent-sign, three exponent digits
  // plus the \0.
  // Note that padding and exponent are exclusive. We still add them up.
  ASSERT(kBufferSize >= 1 + 1 + 1 + kMaxLeadingPaddingZeroes +
                            kMaxTrailingPaddingZeroes + kMaxPrecisionDigits +
                            1 + 1 + 3 + 1);

  ASSERT(kMinPrecisionDigits <= precision && precision <= kMaxPrecisionDigits);

  const double_conversion::DoubleToStringConverter converter(
      kConversionFlags, DoubleToStringConstants::kInfinitySymbol,
      DoubleToStringConstants::kNaNSymbol,
      DoubleToStringConstants::kExponentChar, 0,
      0,  // Ignored in precision mode.
      kMaxLeadingPaddingZeroes, kMaxTrailingPaddingZeroes);

  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
  buffer[kBufferSize - 1] = '\0';
  double_conversion::StringBuilder builder(buffer, kBufferSize);
  bool status = converter.ToPrecision(d, precision, &builder);
  ASSERT(status);
  return String::New(builder.Finalize());
}

bool CStringToDouble(const char* str, intptr_t length, double* result) {
  if (length == 0) {
    return false;
  }

  double_conversion::StringToDoubleConverter converter(
      double_conversion::StringToDoubleConverter::NO_FLAGS, 0.0, 0.0,
      DoubleToStringConstants::kInfinitySymbol,
      DoubleToStringConstants::kNaNSymbol);

  int parsed_count = 0;
  *result =
      converter.StringToDouble(str, static_cast<int>(length), &parsed_count);
  return (parsed_count == length);
}

IntegerPtr DoubleToInteger(Zone* zone, double val) {
  if (isinf(val) || isnan(val)) {
    const Array& args = Array::Handle(zone, Array::New(1));
    args.SetAt(0, String::Handle(zone, String::New("Infinity or NaN toInt")));
    Exceptions::ThrowByType(Exceptions::kUnsupported, args);
  }
  int64_t ival = 0;
  if (val <= static_cast<double>(kMinInt64)) {
    ival = kMinInt64;
  } else if (val >= static_cast<double>(kMaxInt64)) {
    ival = kMaxInt64;
  } else {  // Representable in int64_t.
    ival = static_cast<int64_t>(val);
  }
  return Integer::New(ival);
}

}  // namespace dart
