mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-02-07 04:50:08 +01:00
[jsinterp] Add js_number_to_string
This commit is contained in:
parent
1643686104
commit
7be3f7d4f2
|
@ -9,7 +9,7 @@
|
|||
|
||||
import math
|
||||
|
||||
from yt_dlp.jsinterp import JS_Undefined, JSInterpreter
|
||||
from yt_dlp.jsinterp import JS_Undefined, JSInterpreter, js_number_to_string
|
||||
|
||||
|
||||
class NaN:
|
||||
|
@ -431,6 +431,27 @@ def test_slice(self):
|
|||
self._test('function f(){return "012345678".slice(-1, 1)}', '')
|
||||
self._test('function f(){return "012345678".slice(-3, -1)}', '67')
|
||||
|
||||
def test_js_number_to_string(self):
|
||||
for test, radix, expected in [
|
||||
(0, None, '0'),
|
||||
(-0, None, '0'),
|
||||
(0.0, None, '0'),
|
||||
(-0.0, None, '0'),
|
||||
(math.nan, None, 'NaN'),
|
||||
(-math.nan, None, 'NaN'),
|
||||
(math.inf, None, 'Infinity'),
|
||||
(-math.inf, None, '-Infinity'),
|
||||
(10 ** 21.5, 8, '526665530627250154000000'),
|
||||
(6, 2, '110'),
|
||||
(254, 16, 'fe'),
|
||||
(-10, 2, '-1010'),
|
||||
(-0xff, 2, '-11111111'),
|
||||
(0.1 + 0.2, 16, '0.4cccccccccccd'),
|
||||
(1234.1234, 10, '1234.1234'),
|
||||
# (1000000000000000128, 10, "1000000000000000100")
|
||||
]:
|
||||
assert js_number_to_string(test, radix) == expected
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -95,6 +95,62 @@ def _js_ternary(cndn, if_true=True, if_false=False):
|
|||
return if_true
|
||||
|
||||
|
||||
# Ref: https://es5.github.io/#x9.8.1
|
||||
def js_number_to_string(val: float, radix: int = 10):
|
||||
if radix in (JS_Undefined, None):
|
||||
radix = 10
|
||||
assert radix in range(2, 37), 'radix must be an integer at least 2 and no greater than 36'
|
||||
|
||||
if math.isnan(val):
|
||||
return 'NaN'
|
||||
if val == 0:
|
||||
return '0'
|
||||
if math.isinf(val):
|
||||
return '-Infinity' if val < 0 else 'Infinity'
|
||||
if radix == 10:
|
||||
# TODO: implement special cases
|
||||
...
|
||||
|
||||
ALPHABET = b'0123456789abcdefghijklmnopqrstuvwxyz.-'
|
||||
|
||||
result = collections.deque()
|
||||
sign = val < 0
|
||||
val = abs(val)
|
||||
fraction, integer = math.modf(val)
|
||||
delta = max(math.nextafter(.0, math.inf), math.ulp(val) / 2)
|
||||
|
||||
if fraction >= delta:
|
||||
result.append(-2)
|
||||
while fraction >= delta:
|
||||
delta *= radix
|
||||
fraction, digit = math.modf(fraction * radix)
|
||||
result.append(int(digit))
|
||||
# rounding cringe
|
||||
needs_rounding = fraction > 0.5 or (fraction == 0.5 and int(digit) & 1)
|
||||
if needs_rounding and fraction + delta > 1:
|
||||
for index in reversed(range(1, len(result))):
|
||||
if result[index] + 1 < radix:
|
||||
result[index] += 1
|
||||
break
|
||||
result.pop()
|
||||
|
||||
else:
|
||||
integer += 1
|
||||
break
|
||||
break
|
||||
|
||||
integer, digit = divmod(int(integer), radix)
|
||||
result.appendleft(digit)
|
||||
while integer > 0:
|
||||
integer, digit = divmod(integer, radix)
|
||||
result.appendleft(digit)
|
||||
|
||||
if sign:
|
||||
result.appendleft(-1)
|
||||
|
||||
return bytes(ALPHABET[digit] for digit in result).decode('ascii')
|
||||
|
||||
|
||||
# Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
|
||||
_OPERATORS = { # None => Defined in JSInterpreter._operator
|
||||
'?': None,
|
||||
|
|
Loading…
Reference in New Issue
Block a user