tot - Check-in [8]
Not logged in
[Browse]  [Home]  [Login]  [Reports]  [Search]  [Timeline
  [Patchset
Check-in Number: 8
Date: 2007-Feb-15 22:36:57 (local)
2007-Feb-15 21:36:57 (UTC)
User:rse
Branch:
Comment: add sprintf(3) implementation
Tickets:
Inspections:
Files:
javascript/      added-> 8
javascript/sprintf.html      added-> 8
javascript/sprintf.js      added-> 8
Added: javascript/sprintf.html
===================================================================
--- javascript/sprintf.html	                        (rev 0)
+++ javascript/sprintf.html	2007-02-15 21:36:57 UTC (rev 8)
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+    <head>
+        <title>POSIX sprintf(3) for JavaScript</title>
+        <script type="text/javascript" src="sprintf.js"></script>
+    </head>
+    <body>
+        <h1>POSIX sprintf(3) for JavaScript</h1>
+        <script type="text/javascript">
+            var tests = [
+                /*  tests for %d  */
+                [ "%d", 42, "42" ],
+                [ "%2d", 42, "42" ],
+                [ "%02d", 42, "42" ],
+                [ "%3d", 42, " 42" ],
+                [ "%03d", 42, "042" ],
+                [ "%-3d", 42, "42 " ],
+                [ "%-03d", 42, "42 " ],
+                [ "%d", "xx", "0" ],
+                /*  tests for %x  */
+                [ "%x", 10, "a" ],
+                [ "%2x", 10, " a" ],
+                [ "%02x", 10, "0a" ],
+                [ "%#02x", 10, "0xa" ],
+                [ "%#04x", 10, "0x0a" ],
+                /*  tests for %f  */
+                [ "%f", 4.2, "4.2" ],
+                [ "%.1f", 4.2, "4.2" ],
+                [ "%.2f", 4.2, "4.20" ],
+                [ "%8.4f", 4.12, "  4.1200" ],
+                [ "%8.4f", 4.123456789, "  4.1235" ],
+                /*  tests for %s  */
+                [ "%2s", "test", "test" ],
+                [ "%6s", "test", "  test" ],
+                [ "%-6s", "test", "test  " ],
+            ];
+            for (var i = 0; i < tests.length; i++) {
+                var output = sprintf(tests[i][0], tests[i][1]);
+                var msg = "sprintf(\""+tests[i][0]+"\", "+tests[i][1]+") = \""+output+"\"";
+                if (output != tests[i][2])
+                    msg = msg + " ERROR: expected \""+tests[i][2]+"\"";
+                msg = msg + "<br/>\n";
+                document.write(msg);
+            }
+        </script>
+    </body>
+</html>


Property changes on: javascript/sprintf.html
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+LastChangedDate LastChangedRevision
\ No newline at end of property
Added: javascript/sprintf.js
===================================================================
--- javascript/sprintf.js	                        (rev 0)
+++ javascript/sprintf.js	2007-02-15 21:36:57 UTC (rev 8)
@@ -0,0 +1,216 @@
+/*
+**  sprintf.js -- POSIX sprintf(3) style formatting function for JavaScript
+**  Copyright (c) 2006-2007 Ralf S. Engelschall <rse@engelschall.com>
+**  Partly based on Public Domain code by Jan Moesen <http://jan.moesen.nu/>
+**  Licensed under GPL <http://www.gnu.org/licenses/gpl.txt>
+**
+**  $LastChangedDate$
+**  $LastChangedRevision$
+*/
+
+/*  make sure the ECMAScript 3.0 Number.toFixed() method is available  */
+if (typeof Number.prototype.toFixed != "undefined") {
+    (function(){
+        /*  see http://www.jibbering.com/faq/#FAQ4_6 for details  */
+        function Stretch(Q, L, c) {
+            var S = Q
+            if (c.length > 0)
+                while (S.length < L)
+                    S = c+S;
+            return S;
+        }
+        function StrU(X, M, N) { /* X >= 0.0 */
+            var T, S;
+            S = new String(Math.round(X * Number("1e"+N)));
+            if (S.search && S.search(/\D/) != -1)
+                return ''+X;
+            with (new String(Stretch(S, M+N, '0')))
+                return substring(0, T=(length-N)) + '.' + substring(T);
+        }
+        function Sign(X) {
+            return X < 0 ? '-' : '';
+        }
+        function StrS(X, M, N) {
+            return Sign(X)+StrU(Math.abs(X), M, N);
+        }
+        Number.prototype.toFixed = function (n) { return StrS(this, 1, n) };
+    })();
+}
+
+/*  the sprintf() function  */
+sprintf = function () {
+    /*  argument sanity checking  */
+    if (!arguments || arguments.length < 1)
+        alert("sprintf:ERROR: not enough arguments");
+
+    /*  initialize processing queue  */
+    var argumentnum = 0;
+    var done = "", todo = arguments[argumentnum++];
+
+    /*  parse still to be done format string  */
+    var m;
+    while (m = /^([^%]*)%(\d+$)?([#0 +'-]+)?(\*|\d+)?(\.\*|\.\d+)?([%diouxXfFcs])(.*)$/.exec(todo)) {
+        var pProlog    = m[1],
+            pAccess    = m[2],
+            pFlags     = m[3],
+            pMinLength = m[4],
+            pPrecision = m[5],
+            pType      = m[6],
+            pEpilog    = m[7];
+
+        /*  determine substitution  */
+        var subst;
+        if (pType == '%')
+            /*  special case: escaped percent character  */
+            subst = '%';
+        else {
+            /*  parse padding and justify aspects of flags  */
+            var padWith = ' ';
+            var justifyRight = true;
+            if (pFlags) {
+                if (pFlags.indexOf('0') >= 0)
+                    padWith = '0';
+                if (pFlags.indexOf('-') >= 0) {
+                    padWith = ' ';
+                    justifyRight = false;
+                }
+            }
+            else
+                pFlags = "";
+
+            /*  determine minimum length  */
+            var minLength = -1;
+            if (pMinLength) {
+                if (pMinLength == "*") {
+                    var access = argumentnum++;
+                    if (access >= arguments.length)
+                        alert("sprintf:ERROR: not enough arguments");
+                    minLength = arguments[access];
+                }
+                else
+                    minLength = parseInt(pMinLength, 10);
+            }
+
+            /*  determine precision  */
+            var precision = -1;
+            if (pPrecision) {
+                if (pPrecision == ".*") {
+                    var access = argumentnum++;
+                    if (access >= arguments.length)
+                        alert("sprintf:ERROR: not enough arguments");
+                    precision = arguments[access];
+                }
+                else
+                    precision = parseInt(pPrecision.substring(1), 10);
+            }
+
+            /*  determine how to fetch argument  */
+            var access = argumentnum++;
+            if (pAccess)
+                access = parseInt(pAccess.substring(0, pAccess.length - 1), 10);
+            if (access >= arguments.length)
+                alert("sprintf:ERROR: not enough arguments");
+
+            /*  dispatch into expansions according to type  */
+            var prefix = "";
+            switch (pType) {
+                case 'd':
+                case 'i':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = subst.toString(10);
+                    if (pFlags.indexOf('#') >= 0 && subst >= 0)
+                        subst = "+" + subst;
+                    if (pFlags.indexOf(' ') >= 0 && subst >= 0)
+                        subst = " " + subst;
+                    break;
+                case 'o':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = subst.toString(8);
+                    break;
+                case 'u':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = Math.abs(subst);
+                    subst = subst.toString(10);
+                    break;
+                case 'x':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = subst.toString(16).toLowerCase();
+                    if (pFlags.indexOf('#') >= 0)
+                        prefix = "0x";
+                    break;
+                case 'X':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = subst.toString(16).toLowerCase();
+                    if (pFlags.indexOf('#') >= 0)
+                        prefix = "0X";
+                    break;
+                case 'f':
+                case 'F':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0.0;
+                    subst = 0.0 + subst;
+                    if (precision > -1) {
+                        if (subst.toFixed)
+                            subst = subst.toFixed(precision);
+                        else {
+                            subst = (Math.round(subst * Math.pow(10, precision)) / Math.pow(10, precision));
+                            subst += "0000000000";
+                            subst = subst.substr(0, subst.indexOf(".")+precision+1);
+                        }
+                    }
+                    subst = '' + subst;
+                    if (pFlags.indexOf("'") >= 0) {
+                        var k = 0;
+                        for (var i = (subst.length - 1) - 3; i >= 0; i -= 3) {
+                            subst = subst.substring(0, i) + (k == 0 ? "." : ",") + subst.substring(i);
+                            k = (k + 1) % 2;
+                        }
+                    }
+                    break;
+                case 'c':
+                    subst = arguments[access];
+                    if (typeof subst != "number")
+                        subst = 0;
+                    subst = String.fromCharCode(subst);
+                    break;
+                case 's':
+                    subst = arguments[access];
+                    if (precision > -1)
+                        subst = subst.substr(0, precision);
+                    if (typeof subst != "string")
+                        subst = "";
+                    break;
+            }
+
+            /*  apply optional padding  */
+            var padding = minLength - subst.toString().length - prefix.toString().length;
+            if (padding > 0) {
+                var arrTmp = new Array(padding + 1);
+                if (justifyRight)
+                    subst = arrTmp.join(padWith) + subst;
+                else
+                    subst = subst + arrTmp.join(padWith);
+            }
+
+            /*  add optional prefix  */
+            subst = prefix + subst;
+        }
+
+        /*  update the processing queue  */
+        done = done + pProlog + subst;
+        todo = pEpilog;
+    }
+    return (done + todo);
+}
+


Property changes on: javascript/sprintf.js
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+LastChangedDate LastChangedRevision
\ No newline at end of property