blob: 2373ae0f7f56fd512cca5600509c8b075c693a8d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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 builtin_intl_DecimalNumber_h
#define builtin_intl_DecimalNumber_h
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/Span.h"
#include "mozilla/Variant.h"
#include <stddef.h>
#include <stdint.h>
#include "jstypes.h"
#include "js/TypeDecls.h"
class JSLinearString;
namespace JS {
class JS_PUBLIC_API AutoCheckCannotGC;
}
namespace js::intl {
/**
* Representation of a decimal number in normalized form.
*
* Examples of normalized forms:
* - "123" is normalized to "0.123e3".
* - "0.01e-4" is normalized to "0.1e-5".
* - "12.3" is normalized to "0.123e2".
*
* Note: Internally we leave the decimal point where it lies to avoid copying
* the string, but otherwise ignore it once we calculate the normalized
* exponent.
*
* TODO: Remove unused capabilities once there's a concrete PR for
* <https://github.com/tc39/proposal-intl-numberformat-v3/issues/98>.
*/
class MOZ_STACK_CLASS DecimalNumber final {
using Latin1String = mozilla::Span<const JS::Latin1Char>;
using TwoByteString = mozilla::Span<const char16_t>;
mozilla::Variant<Latin1String, TwoByteString> string_;
char charAt(size_t i) const {
if (string_.is<Latin1String>()) {
return static_cast<char>(string_.as<Latin1String>()[i]);
}
return static_cast<char>(string_.as<TwoByteString>()[i]);
}
// Decimal exponent. Valid range is (INT32_MIN, INT_MAX32].
int32_t exponent_ = 0;
// Start and end position of the significand.
size_t significandStart_ = 0;
size_t significandEnd_ = 0;
// Flag if the number is zero.
bool zero_ = false;
// Flag for negative numbers.
bool negative_ = false;
// Error flag when the exponent is too large.
bool exponentTooLarge_ = false;
template <typename CharT>
explicit DecimalNumber(mozilla::Span<const CharT> string) : string_(string) {}
public:
/** Return true if this decimal is zero. */
bool isZero() const { return zero_; }
/** Return true if this decimal is negative. */
bool isNegative() const { return negative_; }
/** Return true if the exponent is too large. */
bool exponentTooLarge() const { return exponentTooLarge_; }
/** Return the exponent of this decimal. */
int32_t exponent() const { return exponent_; }
// Exposed for testing.
size_t significandStart() const { return significandStart_; }
size_t significandEnd() const { return significandEnd_; }
/**
* Compare this decimal to another decimal. Returns a negative value if this
* decimal is smaller; zero if this decimal is equal; or a positive value if
* this decimal is larger than the input.
*/
int32_t compareTo(const DecimalNumber& other) const;
/**
* Create a decimal number from the input. Returns |mozilla::Nothing| if the
* input can't be parsed.
*/
template <typename CharT>
static mozilla::Maybe<DecimalNumber> from(mozilla::Span<const CharT> chars);
/**
* Create a decimal number from the input. Returns |mozilla::Nothing| if the
* input can't be parsed.
*/
static mozilla::Maybe<DecimalNumber> from(JSLinearString* str,
JS::AutoCheckCannotGC& nogc);
};
} // namespace js::intl
#endif /* builtin_intl_DecimalNumber_h */
|