Skip to content
Browse files

use precise 64-bit parsing for parseInt, add bswap64 test, fixes #768

  • Loading branch information...
1 parent ea655d0 commit d4562d82ed21a1c4fab4b4ef9d98d24a097dada4 @kripken committed Dec 30, 2012
Showing with 152 additions and 23 deletions.
  1. +66 −4 src/library.js
  2. +18 −19 tests/parseInt/output.txt
  3. +68 −0 tests/runner.py
View
70 src/library.js
@@ -3837,9 +3837,71 @@ LibraryManager.library = {
return ret;
},
- strtoll__deps: ['_parseInt'],
+#if USE_TYPED_ARRAYS == 2
+ _parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }],
+ _parseInt64: function(str, endptr, base, min, max, unsign) {
+ var start = str;
+
+ // Skip space.
+ while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
+
+ // Check for a plus/minus sign.
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == '-'.charCodeAt(0)) {
+ str++;
+ } else if ({{{ makeGetValue('str', 0, 'i8') }}} == '+'.charCodeAt(0)) {
+ str++;
+ }
+
+ // Find base.
+ var finalBase = base;
+ if (!finalBase) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == '0'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == 'x'.charCodeAt(0) ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == 'X'.charCodeAt(0)) {
+ finalBase = 16;
+ str += 2;
+ } else {
+ finalBase = 8;
+ str++;
+ }
+ }
+ }
+ if (!finalBase) finalBase = 10;
+
+ // Get digits.
+ var chr;
+ var ok = false;
+ while ((chr = {{{ makeGetValue('str', 0, 'i8') }}}) != 0) {
+ var digit = parseInt(String.fromCharCode(chr), finalBase);
+ if (isNaN(digit)) {
+ break;
+ } else {
+ ok = true;
+ str++;
+ }
+ }
+
+ try {
+ i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign);
+ } catch(e) {
+ ___setErrNo(ERRNO_CODES.ERANGE); // not quite correct
+ }
+
+ // Set end pointer.
+ if (endptr) {
+ {{{ makeSetValue('endptr', 0, 'str', '*') }}}
+ }
+
+ // Unsign if needed. XXX
+
+ ret = i64Math.result.slice(0);
+
+ return ret;
+ },
+#endif
+ strtoll__deps: ['_parseInt64'],
strtoll: function(str, endptr, base) {
- return __parseInt(str, endptr, base, -9223372036854775200, 9223372036854775200, 64); // LLONG_MIN, LLONG_MAX; imprecise.
+ return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX.
},
strtoll_l: 'strtoll', // no locale support yet
strtol__deps: ['_parseInt'],
@@ -3852,9 +3914,9 @@ LibraryManager.library = {
return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX.
},
strtoul_l: 'strtoul', // no locale support yet
- strtoull__deps: ['_parseInt'],
+ strtoull__deps: ['_parseInt64'],
strtoull: function(str, endptr, base) {
- return __parseInt(str, endptr, base, 0, 18446744073709551615, 64, true); // ULONG_MAX; imprecise.
+ return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX.
},
strtoull_l: 'strtoull', // no locale support yet
View
37 tests/parseInt/output.txt
@@ -1,52 +1,50 @@
strtol("-9223372036854775809") = -2147483648
ERR 34
-strtoll("-9223372036854775809") = -9223372036854775000
+strtoll("-9223372036854775809") = -9223372036854775808
ERR 34
strtoul("-9223372036854775809") = 4294967295
ERR 34
-strtoull("-9223372036854775809") = 9223372036854774000
+strtoull("-9223372036854775809") = 9223372036854775807
strtol("-9223372036854775808") = -2147483648
ERR 34
-strtoll("-9223372036854775808") = -9223372036854775000
-ERR 34
+strtoll("-9223372036854775808") = -9223372036854775808
strtoul("-9223372036854775808") = 4294967295
ERR 34
-strtoull("-9223372036854775808") = 9223372036854774000
+strtoull("-9223372036854775808") = 9223372036854775808
strtol("-9223372036854775807") = -2147483648
ERR 34
-strtoll("-9223372036854775807") = -9223372036854775000
-ERR 34
+strtoll("-9223372036854775807") = -9223372036854775807
strtoul("-9223372036854775807") = 4294967295
ERR 34
-strtoull("-9223372036854775807") = 9223372036854774000
+strtoull("-9223372036854775807") = 9223372036854775809
strtol("-2147483649") = -2147483648
ERR 34
strtoll("-2147483649") = -2147483649
strtoul("-2147483649") = 2147483647
-strtoull("-2147483649") = 18446744071562068000
+strtoull("-2147483649") = 18446744071562067967
strtol("-2147483648") = -2147483648
strtoll("-2147483648") = -2147483648
strtoul("-2147483648") = 2147483648
-strtoull("-2147483648") = 18446744071562068000
+strtoull("-2147483648") = 18446744071562067968
strtol("-2147483647") = -2147483647
strtoll("-2147483647") = -2147483647
strtoul("-2147483647") = 2147483649
-strtoull("-2147483647") = 18446744071562068000
+strtoull("-2147483647") = 18446744071562067969
strtol("-5") = -5
strtoll("-5") = -5
strtoul("-5") = 4294967291
-strtoull("-5") = 18446744069414584000
+strtoull("-5") = 18446744073709551611
strtol("-1") = -1
strtoll("-1") = -1
strtoul("-1") = 4294967295
-strtoull("-1") = 18446744069414584000
+strtoull("-1") = 18446744073709551615
strtol("0") = 0
strtoll("0") = 0
@@ -100,27 +98,28 @@ strtoull("4294967296") = 4294967296
strtol("18446744073709551614") = 2147483647
ERR 34
-strtoll("18446744073709551614") = 9223372036854775000
+strtoll("18446744073709551614") = 9223372036854775807
ERR 34
strtoul("18446744073709551614") = 4294967295
ERR 34
-strtoull("18446744073709551614") = 18446744069414584000
+strtoull("18446744073709551614") = 18446744073709551614
strtol("18446744073709551615") = 2147483647
ERR 34
-strtoll("18446744073709551615") = 9223372036854775000
+strtoll("18446744073709551615") = 9223372036854775807
ERR 34
strtoul("18446744073709551615") = 4294967295
ERR 34
-strtoull("18446744073709551615") = 18446744069414584000
+strtoull("18446744073709551615") = 18446744073709551615
strtol("18446744073709551616") = 2147483647
ERR 34
-strtoll("18446744073709551616") = 9223372036854775000
+strtoll("18446744073709551616") = 9223372036854775807
ERR 34
strtoul("18446744073709551616") = 4294967295
ERR 34
-strtoull("18446744073709551616") = 18446744069414584000
+strtoull("18446744073709551616") = 18446744073709551615
+ERR 34
strtol("0x12", 0, 0) = 18
strtol("0x12", 0, 10) = 0
View
68 tests/runner.py
@@ -1192,6 +1192,74 @@ def test_llvm_intrinsics(self):
13
''')
+ def test_bswap64(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include <iostream>
+ #include <string>
+ #include <sstream>
+
+ typedef unsigned long long quint64;
+
+ using namespace std;
+
+ inline quint64 qbswap(quint64 source)
+ {
+ return 0
+ | ((source & quint64(0x00000000000000ffLL)) << 56)
+ | ((source & quint64(0x000000000000ff00LL)) << 40)
+ | ((source & quint64(0x0000000000ff0000LL)) << 24)
+ | ((source & quint64(0x00000000ff000000LL)) << 8)
+ | ((source & quint64(0x000000ff00000000LL)) >> 8)
+ | ((source & quint64(0x0000ff0000000000LL)) >> 24)
+ | ((source & quint64(0x00ff000000000000LL)) >> 40)
+ | ((source & quint64(0xff00000000000000LL)) >> 56);
+ }
+
+ int main()
+ {
+ quint64 v = strtoull("4433ffeeddccbb00", NULL, 16);
+ printf("%lld\n", v);
+
+ const string string64bitInt = "4433ffeeddccbb00";
+ stringstream s(string64bitInt);
+ quint64 int64bitInt = 0;
+ printf("1\n");
+ s >> hex >> int64bitInt;
+ printf("2\n");
+
+ stringstream out;
+ out << hex << qbswap(int64bitInt);
+
+ cout << out.str() << endl;
+ cout << hex << int64bitInt << endl;
+ cout << string64bitInt << endl;
+
+ if (out.str() != "bbccddeeff3344")
+ {
+ cout << "Failed!" << endl;
+ }
+ else
+ {
+ cout << "Succeeded!" << endl;
+ }
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''4914553019779824384
+1
+2
+bbccddeeff3344
+4433ffeeddccbb00
+4433ffeeddccbb00
+Succeeded!
+''')
+
def test_sha1(self):
if self.emcc_args == None: return self.skip('needs ta2')

0 comments on commit d4562d8

Please sign in to comment.
Something went wrong with that request. Please try again.