@@ -17,6 +17,7 @@ class FloatEncoder implements Encoder
17
17
private static $ defaultOptions = [
18
18
'float.integers ' => false ,
19
19
'float.precision ' => 17 ,
20
+ 'float.export ' => false ,
20
21
];
21
22
22
23
public function getDefaultOptions ()
@@ -37,30 +38,27 @@ public function encode($value, $depth, array $options, callable $encode)
37
38
return $ value < 0 ? '-INF ' : 'INF ' ;
38
39
}
39
40
40
- return $ this ->encodeNumber ($ value , $ options );
41
+ return $ this ->encodeNumber ($ value , $ options, $ encode );
41
42
}
42
43
43
44
/**
44
45
* Encodes the number as a PHP number representation.
45
46
* @param float $float The number to encode
46
47
* @param array $options The float encoding options
48
+ * @param callable $encode Callback used to encode values
47
49
* @return string The PHP code representation for the number
48
50
*/
49
- private function encodeNumber ($ float , array $ options )
51
+ private function encodeNumber ($ float , array $ options, callable $ encode )
50
52
{
51
53
if ($ this ->isInteger ($ float , $ options ['float.integers ' ])) {
52
- return number_format ($ float , 0 , ' . ' , '' );
54
+ return $ this -> encodeInteger ($ float , $ encode );
53
55
} elseif ($ float === 0.0 ) {
54
56
return '0.0 ' ;
57
+ } elseif ($ options ['float.export ' ]) {
58
+ return var_export ((float ) $ float , true );
55
59
}
56
60
57
- $ precision = $ options ['float.precision ' ];
58
-
59
- if ($ precision === false ) {
60
- $ precision = ini_get ('serialize_precision ' );
61
- }
62
-
63
- return $ this ->encodeFloat ($ float , $ precision );
61
+ return $ this ->encodeFloat ($ float , $ this ->determinePrecision ($ options ));
64
62
}
65
63
66
64
/**
@@ -80,6 +78,39 @@ private function isInteger($float, $allowIntegers)
80
78
return $ allowIntegers === 'all ' ;
81
79
}
82
80
81
+ /**
82
+ * Encodes the given float as an integer.
83
+ * @param float $float The number to encode
84
+ * @param callable $encode Callback used to encode values
85
+ * @return string The PHP code representation for the number
86
+ */
87
+ private function encodeInteger ($ float , callable $ encode )
88
+ {
89
+ $ minimum = defined ('PHP_INT_MIN ' ) ? PHP_INT_MIN : ~PHP_INT_MAX ;
90
+
91
+ if ($ float >= $ minimum && $ float <= PHP_INT_MAX ) {
92
+ return $ encode ((int ) $ float );
93
+ }
94
+
95
+ return number_format ($ float , 0 , '. ' , '' );
96
+ }
97
+
98
+ /**
99
+ * Determines the float precision based on the options.
100
+ * @param array $options The float encoding options
101
+ * @return int The precision used to encode floats
102
+ */
103
+ private function determinePrecision ($ options )
104
+ {
105
+ $ precision = $ options ['float.precision ' ];
106
+
107
+ if ($ precision === false ) {
108
+ $ precision = defined ('HHVM_VERSION ' ) ? 17 : ini_get ('serialize_precision ' );
109
+ }
110
+
111
+ return max (1 , (int ) $ precision );
112
+ }
113
+
83
114
/**
84
115
* Encodes the number using a floating point representation.
85
116
* @param float $float The number to encode
@@ -88,10 +119,9 @@ private function isInteger($float, $allowIntegers)
88
119
*/
89
120
private function encodeFloat ($ float , $ precision )
90
121
{
91
- $ precision = max (1 , (int ) $ precision );
92
122
$ log = (int ) floor (log (abs ($ float ), 10 ));
93
123
94
- if (abs ($ float ) < self ::FLOAT_MAX && $ log > - 5 && abs ($ log ) < $ precision ) {
124
+ if ($ log > - 5 && abs ($ float ) < self ::FLOAT_MAX && abs ($ log ) < $ precision ) {
95
125
return $ this ->formatFloat ($ float , $ precision - $ log - 1 );
96
126
}
97
127
0 commit comments