Skip to content

Commit 8215a02

Browse files
christophpurrermeta-codesync[bot]
authored andcommitted
Remove double-conversion dependency from DoubleConversions.cpp - RFC (#56110)
Summary: Pull Request resolved: #56110 **Summary** Removes the `double-conversion` dependency from `DoubleConversions.cpp` in the React Native repository. - Removed Dependencies: `double-conversion/double-conversion.h` Updated Code * Modified `DoubleConversions.cpp` to use standard C++ library headers (`cmath` and `cstdio`) instead of `double-conversion`. This change aims to reduce dependencies and simplify the codebase. The removed dependency was previously used for string conversion, which has been replaced with standard C++ library functions. Changelog: [Internal] Differential Revision: D96082175
1 parent 3fb1fea commit 8215a02

1 file changed

Lines changed: 79 additions & 16 deletions

File tree

packages/react-native/ReactCommon/react/renderer/graphics/DoubleConversions.cpp

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,95 @@
77

88
#include "DoubleConversions.h"
99

10-
#include <double-conversion/double-conversion.h>
1110
#include <array>
11+
#include <charconv>
12+
#include <cmath>
1213

1314
namespace facebook::react {
1415

1516
std::string toString(double doubleValue, char suffix) {
16-
// Format taken from folly's toString
17-
static double_conversion::DoubleToStringConverter conv(
18-
0,
19-
nullptr,
20-
nullptr,
21-
'E',
22-
-6, // detail::kConvMaxDecimalInShortestLow,
23-
21, // detail::kConvMaxDecimalInShortestHigh,
24-
6, // max leading padding zeros
25-
1); // max trailing padding zeros
2617
std::array<char, 256> buffer{};
27-
double_conversion::StringBuilder builder(buffer.data(), buffer.size());
28-
if (!conv.ToShortest(doubleValue, &builder)) {
18+
int len = 0;
19+
bool stripZeros = false;
20+
21+
if (!std::isfinite(doubleValue)) {
2922
// Serialize infinite and NaN as 0
30-
builder.AddCharacter('0');
23+
buffer[0] = '0';
24+
len = 1;
25+
} else {
26+
double absValue = std::abs(doubleValue);
27+
28+
// Use fixed notation for values in [1e-6, 1e21), scientific notation
29+
// with uppercase E otherwise. This approximates JavaScript's
30+
// Number.toString() behavior, though %g's default precision of 6
31+
// significant digits may lose precision for values with more digits.
32+
if (absValue != 0.0 && (absValue < 1e-6 || absValue >= 1e21)) {
33+
// %G is like %g but uses uppercase E
34+
auto result = std::to_chars(
35+
buffer.data(),
36+
buffer.data() + buffer.size(),
37+
doubleValue,
38+
std::chars_format::general,
39+
6);
40+
len = result.ec == std::errc{}
41+
? static_cast<int>(result.ptr - buffer.data())
42+
: 0;
43+
// Uppercase 'e' to 'E' to match %G behavior
44+
for (int i = 0; i < len; ++i) {
45+
if (buffer[static_cast<size_t>(i)] == 'e') {
46+
buffer[static_cast<size_t>(i)] = 'E';
47+
break;
48+
}
49+
}
50+
} else if (
51+
(absValue >= 1e-6 && absValue < 1e-4) ||
52+
(absValue >= 1e6 && absValue < 1e21)) {
53+
// %g switches to scientific notation for exponents < -4 or >= precision
54+
// (default 6), so we use %f for [1e-6, 1e-4) and [1e6, 1e21).
55+
auto result = std::to_chars(
56+
buffer.data(),
57+
buffer.data() + buffer.size(),
58+
doubleValue,
59+
std::chars_format::fixed,
60+
20);
61+
len = result.ec == std::errc{}
62+
? static_cast<int>(result.ptr - buffer.data())
63+
: 0;
64+
stripZeros = true;
65+
} else {
66+
auto result = std::to_chars(
67+
buffer.data(),
68+
buffer.data() + buffer.size(),
69+
doubleValue,
70+
std::chars_format::general,
71+
6);
72+
len = result.ec == std::errc{}
73+
? static_cast<int>(result.ptr - buffer.data())
74+
: 0;
75+
}
76+
77+
if (len <= 0 || static_cast<size_t>(len) >= buffer.size()) {
78+
buffer[0] = '0';
79+
len = 1;
80+
} else if (stripZeros) {
81+
// Strip trailing zeros and unnecessary decimal point
82+
auto end = static_cast<size_t>(len);
83+
while (end > 0 && buffer[end - 1] == '0') {
84+
--end;
85+
}
86+
if (end > 0 && buffer[end - 1] == '.') {
87+
--end;
88+
}
89+
len = static_cast<int>(end);
90+
}
3191
}
92+
93+
auto resultLen = static_cast<size_t>(len);
3294
if (suffix != '\0') {
33-
builder.AddCharacter(suffix);
95+
buffer[resultLen] = suffix;
96+
++resultLen;
3497
}
35-
return builder.Finalize();
98+
return {buffer.data(), resultLen};
3699
}
37100

38101
} // namespace facebook::react

0 commit comments

Comments
 (0)