2013-05-05 16:23:18 -07:00
|
|
|
diff --git a/mfbt/decimal/Decimal.cpp b/mfbt/decimal/Decimal.cpp
|
|
|
|
--- a/mfbt/decimal/Decimal.cpp
|
|
|
|
+++ b/mfbt/decimal/Decimal.cpp
|
|
|
|
@@ -23,27 +23,22 @@
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
-#include "config.h"
|
|
|
|
#include "Decimal.h"
|
|
|
|
+#include "moz-decimal-utils.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
-#include <wtf/Assertions.h>
|
|
|
|
-#include <wtf/MathExtras.h>
|
|
|
|
-#include <wtf/Noncopyable.h>
|
|
|
|
-#include <wtf/text/StringBuilder.h>
|
|
|
|
-
|
|
|
|
namespace WebCore {
|
|
|
|
|
|
|
|
namespace DecimalPrivate {
|
|
|
|
|
|
|
|
static int const ExponentMax = 1023;
|
|
|
|
static int const ExponentMin = -1023;
|
|
|
|
static int const Precision = 18;
|
|
|
|
|
|
|
|
@@ -685,17 +680,17 @@ Decimal Decimal::floor() const
|
|
|
|
result += 1;
|
|
|
|
}
|
|
|
|
return Decimal(sign(), 0, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Decimal Decimal::fromDouble(double doubleValue)
|
|
|
|
{
|
|
|
|
if (std::isfinite(doubleValue))
|
|
|
|
- return fromString(String::numberToStringECMAScript(doubleValue));
|
|
|
|
+ return fromString(mozToString(doubleValue));
|
|
|
|
|
|
|
|
if (std::isinf(doubleValue))
|
|
|
|
return infinity(doubleValue < 0 ? Negative : Positive);
|
|
|
|
|
|
|
|
return nan();
|
|
|
|
}
|
|
|
|
|
|
|
|
Decimal Decimal::fromString(const String& str)
|
|
|
|
@@ -937,17 +932,17 @@ Decimal Decimal::round() const
|
|
|
|
result /= 10;
|
|
|
|
return Decimal(sign(), 0, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
double Decimal::toDouble() const
|
|
|
|
{
|
|
|
|
if (isFinite()) {
|
|
|
|
bool valid;
|
|
|
|
- const double doubleValue = toString().toDouble(&valid);
|
|
|
|
+ const double doubleValue = mozToDouble(toString(), &valid);
|
|
|
|
return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isInfinity())
|
|
|
|
return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
|
|
|
|
|
|
|
|
return std::numeric_limits<double>::quiet_NaN();
|
|
|
|
}
|
|
|
|
@@ -990,17 +985,17 @@ String Decimal::toString() const
|
|
|
|
++coefficient;
|
|
|
|
|
|
|
|
while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
|
|
|
|
coefficient /= 10;
|
|
|
|
++originalExponent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- const String digits = String::number(coefficient);
|
|
|
|
+ const String digits = mozToString(coefficient);
|
|
|
|
int coefficientLength = static_cast<int>(digits.length());
|
|
|
|
const int adjustedExponent = originalExponent + coefficientLength - 1;
|
|
|
|
if (originalExponent <= 0 && adjustedExponent >= -6) {
|
|
|
|
if (!originalExponent) {
|
|
|
|
builder.append(digits);
|
|
|
|
return builder.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1032,15 +1027,28 @@ String Decimal::toString() const
|
|
|
|
if (adjustedExponent) {
|
|
|
|
builder.append(adjustedExponent < 0 ? "e" : "e+");
|
|
|
|
builder.appendNumber(adjustedExponent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return builder.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
+bool Decimal::toString(char* strBuf, size_t bufLength) const
|
|
|
|
+{
|
|
|
|
+ ASSERT(bufLength > 0);
|
|
|
|
+ String str = toString();
|
|
|
|
+ size_t length = str.copy(strBuf, bufLength);
|
|
|
|
+ if (length < bufLength) {
|
|
|
|
+ strBuf[length] = '\0';
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ strBuf[bufLength - 1] = '\0';
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
Decimal Decimal::zero(Sign sign)
|
|
|
|
{
|
|
|
|
return Decimal(EncodedData(sign, EncodedData::ClassZero));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace WebCore
|
|
|
|
|
|
|
|
diff --git a/mfbt/decimal/Decimal.h b/mfbt/decimal/Decimal.h
|
|
|
|
--- a/mfbt/decimal/Decimal.h
|
|
|
|
+++ b/mfbt/decimal/Decimal.h
|
|
|
|
@@ -23,24 +23,41 @@
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Imported from:
|
|
|
|
+ * http://src.chromium.org/viewvc/blink/trunk/Source/core/platform/Decimal.h
|
|
|
|
+ * Check hg log for the svn rev of the last update from Blink core.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
#ifndef Decimal_h
|
|
|
|
#define Decimal_h
|
|
|
|
|
|
|
|
+#include "mozilla/Assertions.h"
|
|
|
|
+#include "mozilla/StandardInteger.h"
|
|
|
|
#include "mozilla/Types.h"
|
|
|
|
|
|
|
|
-#include <stdint.h>
|
|
|
|
-#include <wtf/Assertions.h>
|
|
|
|
-#include <wtf/text/WTFString.h>
|
|
|
|
+#include <string>
|
|
|
|
+
|
|
|
|
+#ifndef ASSERT
|
|
|
|
+#define DEFINED_ASSERT_FOR_DECIMAL_H 1
|
|
|
|
+#define ASSERT MOZ_ASSERT
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+// To use WTF_MAKE_FAST_ALLOCATED we'd need:
|
|
|
|
+// http://src.chromium.org/viewvc/blink/trunk/Source/wtf/FastMalloc.h
|
|
|
|
+// Since we don't allocate Decimal objects, no need.
|
|
|
|
+#define WTF_MAKE_FAST_ALLOCATED \
|
|
|
|
+ void ignore_this_dummy_method() MOZ_DELETE
|
|
|
|
|
|
|
|
namespace WebCore {
|
|
|
|
|
|
|
|
namespace DecimalPrivate {
|
|
|
|
class SpecialValueHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This class represents decimal base floating point number.
|
|
|
|
@@ -136,27 +153,28 @@ public:
|
|
|
|
MFBT_API Decimal abs() const;
|
|
|
|
MFBT_API Decimal ceiling() const;
|
|
|
|
MFBT_API Decimal floor() const;
|
|
|
|
MFBT_API Decimal remainder(const Decimal&) const;
|
|
|
|
MFBT_API Decimal round() const;
|
|
|
|
|
|
|
|
MFBT_API double toDouble() const;
|
|
|
|
// Note: toString method supports infinity and nan but fromString not.
|
|
|
|
- MFBT_API String toString() const;
|
|
|
|
+ MFBT_API std::string toString() const;
|
|
|
|
+ MFBT_API bool toString(char* strBuf, size_t bufLength) const;
|
|
|
|
|
|
|
|
static MFBT_API Decimal fromDouble(double);
|
|
|
|
// fromString supports following syntax EBNF:
|
|
|
|
// number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
|
|
|
|
// | sign? '.' digit+ (exponent-marker sign? digit+)?
|
|
|
|
// sign ::= '+' | '-'
|
|
|
|
// exponent-marker ::= 'e' | 'E'
|
|
|
|
// digit ::= '0' | '1' | ... | '9'
|
|
|
|
// Note: fromString doesn't support "infinity" and "nan".
|
|
|
|
- static MFBT_API Decimal fromString(const String&);
|
|
|
|
+ static MFBT_API Decimal fromString(const std::string& aValue);
|
|
|
|
static MFBT_API Decimal infinity(Sign);
|
|
|
|
static MFBT_API Decimal nan();
|
|
|
|
static MFBT_API Decimal zero(Sign);
|
|
|
|
|
|
|
|
// You should not use below methods. We expose them for unit testing.
|
|
|
|
MFBT_API explicit Decimal(const EncodedData&);
|
|
|
|
const EncodedData& value() const { return m_data; }
|
|
|
|
|
|
|
|
@@ -175,10 +193,21 @@ private:
|
|
|
|
|
|
|
|
Sign sign() const { return m_data.sign(); }
|
|
|
|
|
|
|
|
EncodedData m_data;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace WebCore
|
|
|
|
|
|
|
|
+namespace mozilla {
|
|
|
|
+ typedef WebCore::Decimal Decimal;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#undef WTF_MAKE_FAST_ALLOCATED
|
|
|
|
+
|
|
|
|
+#ifdef DEFINED_ASSERT_FOR_DECIMAL_H
|
|
|
|
+#undef DEFINED_ASSERT_FOR_DECIMAL_H
|
|
|
|
+#undef ASSERT
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#endif // Decimal_h
|
|
|
|
|
|
|
|
diff --git a/mfbt/decimal/moz-decimal-utils.h b/mfbt/decimal/moz-decimal-utils.h
|
|
|
|
new file mode 100644
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/mfbt/decimal/moz-decimal-utils.h
|
|
|
|
@@ -0,0 +1,109 @@
|
|
|
|
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
+
|
|
|
|
+#ifndef MOZ_DECIMAL_UTILS_H
|
|
|
|
+#define MOZ_DECIMAL_UTILS_H
|
|
|
|
+
|
|
|
|
+// This file contains extra includes, defines and typedefs to allow compilation
|
|
|
|
+// of Decimal.cpp under the Mozilla source without blink core dependencies. Do
|
|
|
|
+// not include it into any file other than Decimal.cpp.
|
|
|
|
+
|
|
|
|
+#include "../double-conversion/double-conversion.h"
|
|
|
|
+#include "mozilla/Util.h"
|
|
|
|
+#include "mozilla/Casting.h"
|
|
|
|
+#include "mozilla/FloatingPoint.h"
|
|
|
|
+#include "mozilla/NullPtr.h"
|
|
|
|
+
|
|
|
|
+#include <cmath>
|
|
|
|
+#include <cstring>
|
|
|
|
+#include <iomanip>
|
|
|
|
+#include <limits>
|
|
|
|
+#include <sstream>
|
|
|
|
+
|
|
|
|
+#ifndef UINT64_C
|
|
|
|
+// For Android toolchain
|
|
|
|
+#define UINT64_C(c) (c ## ULL)
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef ASSERT
|
|
|
|
+#undef ASSERT
|
|
|
|
+#endif
|
|
|
|
+#define ASSERT MOZ_ASSERT
|
|
|
|
+
|
2013-06-28 19:20:12 -07:00
|
|
|
+#define ASSERT_NOT_REACHED() MOZ_ASSUME_UNREACHABLE()
|
2013-05-05 16:23:18 -07:00
|
|
|
+
|
|
|
|
+#define WTF_MAKE_NONCOPYABLE(ClassName) \
|
|
|
|
+ private: \
|
|
|
|
+ ClassName(const ClassName&) MOZ_DELETE; \
|
|
|
|
+ void operator=(const ClassName&) MOZ_DELETE;
|
|
|
|
+
|
|
|
|
+#if defined(_MSC_VER) && (_MSC_VER <= 1700)
|
|
|
|
+namespace std {
|
|
|
|
+ inline bool isinf(double num) { return MOZ_DOUBLE_IS_INFINITE(num); }
|
|
|
|
+ inline bool isnan(double num) { return MOZ_DOUBLE_IS_NaN(num); }
|
|
|
|
+ inline bool isfinite(double num) { return MOZ_DOUBLE_IS_FINITE(num); }
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+typedef std::string String;
|
|
|
|
+
|
|
|
|
+double mozToDouble(const String &aStr, bool *valid) {
|
|
|
|
+ double_conversion::StringToDoubleConverter converter(
|
|
|
|
+ double_conversion::StringToDoubleConverter::NO_FLAGS,
|
|
|
|
+ MOZ_DOUBLE_NaN(), MOZ_DOUBLE_NaN(), nullptr, nullptr);
|
|
|
|
+ const char* str = aStr.c_str();
|
|
|
|
+ int length = mozilla::SafeCast<int>(strlen(str));
|
|
|
|
+ int processed_char_count; // unused - NO_FLAGS requires the whole string to parse
|
|
|
|
+ double result = converter.StringToDouble(str, length, &processed_char_count);
|
|
|
|
+ *valid = MOZ_DOUBLE_IS_FINITE(result);
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String mozToString(double aNum) {
|
|
|
|
+ char buffer[64];
|
|
|
|
+ int buffer_length = mozilla::ArrayLength(buffer);
|
|
|
|
+ const double_conversion::DoubleToStringConverter& converter =
|
|
|
|
+ double_conversion::DoubleToStringConverter::EcmaScriptConverter();
|
|
|
|
+ double_conversion::StringBuilder builder(buffer, buffer_length);
|
|
|
|
+ converter.ToShortest(aNum, &builder);
|
|
|
|
+ return String(builder.Finalize());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String mozToString(int64_t aNum) {
|
|
|
|
+ std::ostringstream o;
|
|
|
|
+ o << std::setprecision(std::numeric_limits<int64_t>::digits10) << aNum;
|
|
|
|
+ return o.str();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String mozToString(uint64_t aNum) {
|
|
|
|
+ std::ostringstream o;
|
|
|
|
+ o << std::setprecision(std::numeric_limits<uint64_t>::digits10) << aNum;
|
|
|
|
+ return o.str();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class StringBuilder
|
|
|
|
+{
|
|
|
|
+public:
|
|
|
|
+ void append(char c) {
|
|
|
|
+ mStr += c;
|
|
|
|
+ }
|
|
|
|
+ void appendLiteral(const char *aStr) {
|
|
|
|
+ mStr += aStr;
|
|
|
|
+ }
|
|
|
|
+ void appendNumber(int aNum) {
|
|
|
|
+ mStr += mozToString(int64_t(aNum));
|
|
|
|
+ }
|
|
|
|
+ void append(const String& aStr) {
|
|
|
|
+ mStr += aStr;
|
|
|
|
+ }
|
|
|
|
+ std::string toString() const {
|
|
|
|
+ return mStr;
|
|
|
|
+ }
|
|
|
|
+private:
|
|
|
|
+ std::string mStr;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|