diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-03-18 13:08:24 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-03-18 13:08:24 -0700 |
commit | cc35ae70ece1f93a23bd666bda395fbb697bbda8 (patch) | |
tree | a2f13b68b85180117a88d1070838bba92d838c18 | |
parent | e330447ce72d8ef4c678ab5354b44163b57dfed0 (diff) |
switchify the main formatString loop
-rw-r--r-- | src/library.js | 388 |
1 files changed, 201 insertions, 187 deletions
diff --git a/src/library.js b/src/library.js index 79f1c285..d7efb34f 100644 --- a/src/library.js +++ b/src/library.js @@ -2782,235 +2782,249 @@ LibraryManager.library = { next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}}; // Handle type specifier. - if (['d', 'i', 'u', 'o', 'x', 'X', 'p'].indexOf(String.fromCharCode(next)) != -1) { - // Integer. - var signed = next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}; - argSize = argSize || 4; - var currArg = getNextArg('i' + (argSize * 8)); + switch (String.fromCharCode(next)) { + case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': { + // Integer. + var signed = next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}; + argSize = argSize || 4; + var currArg = getNextArg('i' + (argSize * 8)); #if PRECISE_I64_MATH - var origArg = currArg; + var origArg = currArg; #endif - var argText; + var argText; #if USE_TYPED_ARRAYS == 2 - // Flatten i64-1 [low, high] into a (slightly rounded) double - if (argSize == 8) { - currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == {{{ charCode('u') }}}); - } + // Flatten i64-1 [low, high] into a (slightly rounded) double + if (argSize == 8) { + currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == {{{ charCode('u') }}}); + } #endif - // Truncate to requested size. - if (argSize <= 4) { - var limit = Math.pow(256, argSize) - 1; - currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); - } - // Format the number. - var currAbsArg = Math.abs(currArg); - var prefix = ''; - if (next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}) { + // Truncate to requested size. + if (argSize <= 4) { + var limit = Math.pow(256, argSize) - 1; + currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8); + } + // Format the number. + var currAbsArg = Math.abs(currArg); + var prefix = ''; + if (next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}) { #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else #endif - argText = reSign(currArg, 8 * argSize, 1).toString(10); - } else if (next == {{{ charCode('u') }}}) { + argText = reSign(currArg, 8 * argSize, 1).toString(10); + } else if (next == {{{ charCode('u') }}}) { #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else + if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else #endif - argText = unSign(currArg, 8 * argSize, 1).toString(10); - currArg = Math.abs(currArg); - } else if (next == {{{ charCode('o') }}}) { - argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); - } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { - prefix = flagAlternative ? '0x' : ''; + argText = unSign(currArg, 8 * argSize, 1).toString(10); + currArg = Math.abs(currArg); + } else if (next == {{{ charCode('o') }}}) { + argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); + } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { + prefix = flagAlternative ? '0x' : ''; #if PRECISE_I64_MATH - if (argSize == 8 && i64Math) { - if (origArg[1]) { - argText = (origArg[1]>>>0).toString(16); - var lower = (origArg[0]>>>0).toString(16); - while (lower.length < 8) lower = '0' + lower; - argText += lower; + if (argSize == 8 && i64Math) { + if (origArg[1]) { + argText = (origArg[1]>>>0).toString(16); + var lower = (origArg[0]>>>0).toString(16); + while (lower.length < 8) lower = '0' + lower; + argText += lower; + } else { + argText = (origArg[0]>>>0).toString(16); + } + } else +#endif + if (currArg < 0) { + // Represent negative numbers in hex as 2's complement. + currArg = -currArg; + argText = (currAbsArg - 1).toString(16); + var buffer = []; + for (var i = 0; i < argText.length; i++) { + buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + } + argText = buffer.join(''); + while (argText.length < argSize * 2) argText = 'f' + argText; } else { - argText = (origArg[0]>>>0).toString(16); + argText = currAbsArg.toString(16); } - } else -#endif - if (currArg < 0) { - // Represent negative numbers in hex as 2's complement. - currArg = -currArg; - argText = (currAbsArg - 1).toString(16); - var buffer = []; - for (var i = 0; i < argText.length; i++) { - buffer.push((0xF - parseInt(argText[i], 16)).toString(16)); + if (next == {{{ charCode('X') }}}) { + prefix = prefix.toUpperCase(); + argText = argText.toUpperCase(); + } + } else if (next == {{{ charCode('p') }}}) { + if (currAbsArg === 0) { + argText = '(nil)'; + } else { + prefix = '0x'; + argText = currAbsArg.toString(16); } - argText = buffer.join(''); - while (argText.length < argSize * 2) argText = 'f' + argText; - } else { - argText = currAbsArg.toString(16); - } - if (next == {{{ charCode('X') }}}) { - prefix = prefix.toUpperCase(); - argText = argText.toUpperCase(); - } - } else if (next == {{{ charCode('p') }}}) { - if (currAbsArg === 0) { - argText = '(nil)'; - } else { - prefix = '0x'; - argText = currAbsArg.toString(16); } - } - if (precisionSet) { - while (argText.length < precision) { - argText = '0' + argText; + if (precisionSet) { + while (argText.length < precision) { + argText = '0' + argText; + } } - } - // Add sign if needed - if (flagAlwaysSigned) { - if (currArg < 0) { - prefix = '-' + prefix; - } else { - prefix = '+' + prefix; + // Add sign if needed + if (flagAlwaysSigned) { + if (currArg < 0) { + prefix = '-' + prefix; + } else { + prefix = '+' + prefix; + } } - } - // Add padding. - while (prefix.length + argText.length < width) { - if (flagLeftAlign) { - argText += ' '; - } else { - if (flagZeroPad) { - argText = '0' + argText; + // Add padding. + while (prefix.length + argText.length < width) { + if (flagLeftAlign) { + argText += ' '; } else { - prefix = ' ' + prefix; + if (flagZeroPad) { + argText = '0' + argText; + } else { + prefix = ' ' + prefix; + } } } + + // Insert the result into the buffer. + argText = prefix + argText; + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; } + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': { + // Float. + var currArg = getNextArg('double'); + var argText; + + if (isNaN(currArg)) { + argText = 'nan'; + flagZeroPad = false; + } else if (!isFinite(currArg)) { + argText = (currArg < 0 ? '-' : '') + 'inf'; + flagZeroPad = false; + } else { + var isGeneral = false; + var effectivePrecision = Math.min(precision, 20); + + // Convert g/G to f/F or e/E, as per: + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html + if (next == {{{ charCode('g') }}} || next == {{{ charCode('G') }}}) { + isGeneral = true; + precision = precision || 1; + var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); + if (precision > exponent && exponent >= -4) { + next = ((next == {{{ charCode('g') }}}) ? 'f' : 'F').charCodeAt(0); + precision -= exponent + 1; + } else { + next = ((next == {{{ charCode('g') }}}) ? 'e' : 'E').charCodeAt(0); + precision--; + } + effectivePrecision = Math.min(precision, 20); + } - // Insert the result into the buffer. - argText = prefix + argText; - argText.split('').forEach(function(chr) { - ret.push(chr.charCodeAt(0)); - }); - } else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) { - // Float. - var currArg = getNextArg('double'); - var argText; - - if (isNaN(currArg)) { - argText = 'nan'; - flagZeroPad = false; - } else if (!isFinite(currArg)) { - argText = (currArg < 0 ? '-' : '') + 'inf'; - flagZeroPad = false; - } else { - var isGeneral = false; - var effectivePrecision = Math.min(precision, 20); - - // Convert g/G to f/F or e/E, as per: - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html - if (next == {{{ charCode('g') }}} || next == {{{ charCode('G') }}}) { - isGeneral = true; - precision = precision || 1; - var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10); - if (precision > exponent && exponent >= -4) { - next = ((next == {{{ charCode('g') }}}) ? 'f' : 'F').charCodeAt(0); - precision -= exponent + 1; + if (next == {{{ charCode('e') }}} || next == {{{ charCode('E') }}}) { + argText = currArg.toExponential(effectivePrecision); + // Make sure the exponent has at least 2 digits. + if (/[eE][-+]\d$/.test(argText)) { + argText = argText.slice(0, -1) + '0' + argText.slice(-1); + } + } else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) { + argText = currArg.toFixed(effectivePrecision); + } + + var parts = argText.split('e'); + if (isGeneral && !flagAlternative) { + // Discard trailing zeros and periods. + while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && + (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { + parts[0] = parts[0].slice(0, -1); + } } else { - next = ((next == {{{ charCode('g') }}}) ? 'e' : 'E').charCodeAt(0); - precision--; + // Make sure we have a period in alternative mode. + if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; + // Zero pad until required precision. + while (precision > effectivePrecision++) parts[0] += '0'; } - effectivePrecision = Math.min(precision, 20); - } + argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); - if (next == {{{ charCode('e') }}} || next == {{{ charCode('E') }}}) { - argText = currArg.toExponential(effectivePrecision); - // Make sure the exponent has at least 2 digits. - if (/[eE][-+]\d$/.test(argText)) { - argText = argText.slice(0, -1) + '0' + argText.slice(-1); + // Capitalize 'E' if needed. + if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase(); + + // Add sign. + if (flagAlwaysSigned && currArg >= 0) { + argText = '+' + argText; } - } else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) { - argText = currArg.toFixed(effectivePrecision); } - var parts = argText.split('e'); - if (isGeneral && !flagAlternative) { - // Discard trailing zeros and periods. - while (parts[0].length > 1 && parts[0].indexOf('.') != -1 && - (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) { - parts[0] = parts[0].slice(0, -1); + // Add padding. + while (argText.length < width) { + if (flagLeftAlign) { + argText += ' '; + } else { + if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { + argText = argText[0] + '0' + argText.slice(1); + } else { + argText = (flagZeroPad ? '0' : ' ') + argText; + } } - } else { - // Make sure we have a period in alternative mode. - if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.'; - // Zero pad until required precision. - while (precision > effectivePrecision++) parts[0] += '0'; } - argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : ''); - // Capitalize 'E' if needed. - if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase(); + // Adjust case. + if (next < {{{ charCode('a') }}}) argText = argText.toUpperCase(); - // Add sign. - if (flagAlwaysSigned && currArg >= 0) { - argText = '+' + argText; - } + // Insert the result into the buffer. + argText.split('').forEach(function(chr) { + ret.push(chr.charCodeAt(0)); + }); + break; } - - // Add padding. - while (argText.length < width) { + case 's': { + // String. + var arg = getNextArg('i8*') || nullString; + var argLength = _strlen(arg); + if (precisionSet) argLength = Math.min(argLength, precision); + if (!flagLeftAlign) { + while (argLength < width--) { + ret.push({{{ charCode(' ') }}}); + } + } + for (var i = 0; i < argLength; i++) { + ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); + } if (flagLeftAlign) { - argText += ' '; - } else { - if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) { - argText = argText[0] + '0' + argText.slice(1); - } else { - argText = (flagZeroPad ? '0' : ' ') + argText; + while (argLength < width--) { + ret.push({{{ charCode(' ') }}}); } } + break; } - - // Adjust case. - if (next < {{{ charCode('a') }}}) argText = argText.toUpperCase(); - - // Insert the result into the buffer. - argText.split('').forEach(function(chr) { - ret.push(chr.charCodeAt(0)); - }); - } else if (next == {{{ charCode('s') }}}) { - // String. - var arg = getNextArg('i8*') || nullString; - var argLength = _strlen(arg); - if (precisionSet) argLength = Math.min(argLength, precision); - if (!flagLeftAlign) { - while (argLength < width--) { + case 'c': { + // Character. + if (flagLeftAlign) ret.push(getNextArg('i8')); + while (--width > 0) { ret.push({{{ charCode(' ') }}}); } + if (!flagLeftAlign) ret.push(getNextArg('i8')); + break; } - for (var i = 0; i < argLength; i++) { - ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); - } - if (flagLeftAlign) { - while (argLength < width--) { - ret.push({{{ charCode(' ') }}}); - } + case 'n': { + // Write the length written so far to the next parameter. + var ptr = getNextArg('i32*'); + {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}} + break; } - } else if (next == {{{ charCode('c') }}}) { - // Character. - if (flagLeftAlign) ret.push(getNextArg('i8')); - while (--width > 0) { - ret.push({{{ charCode(' ') }}}); + case '%': { + // Literal percent sign. + ret.push(curr); + break; } - if (!flagLeftAlign) ret.push(getNextArg('i8')); - } else if (next == {{{ charCode('n') }}}) { - // Write the length written so far to the next parameter. - var ptr = getNextArg('i32*'); - {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}} - } else if (next == {{{ charCode('%') }}}) { - // Literal percent sign. - ret.push(curr); - } else { - // Unknown specifiers remain untouched. - for (var i = startTextIndex; i < textIndex + 2; i++) { - ret.push({{{ makeGetValue(0, 'i', 'i8') }}}); + default: { + // Unknown specifiers remain untouched. + for (var i = startTextIndex; i < textIndex + 2; i++) { + ret.push({{{ makeGetValue(0, 'i', 'i8') }}}); + } } } textIndex += 2; |