r18911: add a JSON encoder
authorDerrell Lipman <derrell@samba.org>
Tue, 26 Sep 2006 02:26:36 +0000 (02:26 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:20:20 +0000 (14:20 -0500)
(This used to be commit 774e87974951a03663a1efd15dfde3d012bcf526)

jsonrpc/json.esp [new file with mode: 0644]

diff --git a/jsonrpc/json.esp b/jsonrpc/json.esp
new file mode 100644 (file)
index 0000000..d06a173
--- /dev/null
@@ -0,0 +1,213 @@
+<%
+
+/*
+ * Copyright:
+ *   (C) 2006 by Derrell Lipman
+ *       All rights reserved
+ *
+ * License:
+ *   LGPL 2.1: http://creativecommons.org/licenses/LGPL/2.1/
+ */
+
+/*
+ * This module provides a JSON encoder.
+ */
+
+
+/* escape a string as required by json */
+function _escape(s)
+{
+    var i;
+    var arr = new Array();
+
+    for (i = 0; i < strlen(s); i++)
+    {
+        var c = substr(s, i, 1);
+        if (c == '\x00')
+        {
+            arr[i] = '\\u0000';
+        }
+        if (Json._internal.convert[c] != undefined)
+        {
+            arr[i] = Json._internal.convert[c];
+        }
+        else
+        {
+            arr[i] = c;
+        }
+    }
+
+    return join("", arr);
+}
+
+/* encode an arbitrary object.  called recursively, for object and array */
+function _encode(o)
+{
+    var type = nativeTypeOf(o);
+
+    if (type == "undefined")
+    {
+        return "null";          /* you really shouldn't count on this! */
+    }
+    else if (type == "null")
+    {
+        return "null";
+    }
+    else if (type == "boolean")
+    {
+        if (o)
+        {
+            return "true";
+        }
+        else
+        {
+            return "false";
+        }
+    }
+    else if (type == "c_function" ||
+             type == "js_function" ||
+             type == "string_c_function")
+    {
+        /* no output */
+    }
+    else if (type == "float" ||
+             type == "integer" ||
+             type == "integer64" ||
+             type == "pointer")
+    {
+        return (o + 0);
+    }
+    else if (type == "object")
+    {
+        var buf;
+
+        /* Is this an array or an ordinary object? */
+        if (o["length"] != undefined)
+        {
+            var i;
+
+            /* Assume it's an array if there's a length field */
+            buf = "[";
+            for (i = 0; i < o.length; i++)
+            {
+                /*
+                 * NOTE: We don't support sparse arrays nor associative
+                 * arrays.  Should we later want to do either, we're supposed
+                 * to send it as an object rather than as an array.
+                 */
+                if (i > 0)
+                {
+                    buf = buf + ",";
+                }
+                buf = buf + this.encode(o[i]);
+            }
+            buf = buf + "]";
+        }
+        else
+        {
+            /* No length field, so it must be an ordinary object */
+            var key;
+            var first = true;
+
+            buf = "{";
+            for (key in o)
+            {
+                if (! first)
+                {
+                    buf = buf + ",";
+                }
+                buf = buf + '"' + key + '":' + this.encode(o[key]);
+                first = false;
+            }
+            buf = buf + "}";
+        }
+
+        return buf;
+    }
+    else if (type == "string")
+    {
+        return '"' + this._internal.escape(o) + '"';
+    }
+}
+
+/* Allocate the public Json access object */
+Json = new Object();
+
+/* Json.encode(): encode an arbitrary object */
+Json.encode = _encode;
+_encode = null;
+
+/* Internal stuff, not for external access */
+Json._internal = new Object();
+
+Json._internal.escape = _escape;
+_escape = null;
+
+Json._internal.convert = new Object();
+Json._internal.convert['\b'] = '\\b';
+Json._internal.convert['\t'] = '\\t';
+Json._internal.convert['\n'] = '\\n';
+Json._internal.convert['\f'] = '\\f';
+Json._internal.convert['\r'] = '\\r';
+Json._internal.convert['"'] = '\\"';
+Json._internal.convert['\\'] = '\\\\';
+Json._internal.convert['\x01'] = '\\u0001';
+Json._internal.convert['\x02'] = '\\u0002';
+Json._internal.convert['\x03'] = '\\u0003';
+Json._internal.convert['\x04'] = '\\u0004';
+Json._internal.convert['\x05'] = '\\u0005';
+Json._internal.convert['\x06'] = '\\u0006';
+Json._internal.convert['\x07'] = '\\u0007';
+Json._internal.convert['\x08'] = '\\u0008';
+Json._internal.convert['\x09'] = '\\u0009';
+Json._internal.convert['\x0a'] = '\\u000a';
+Json._internal.convert['\x0b'] = '\\u000b';
+Json._internal.convert['\x0c'] = '\\u000c';
+Json._internal.convert['\x0d'] = '\\u000d';
+Json._internal.convert['\x0e'] = '\\u000e';
+Json._internal.convert['\x0f'] = '\\u000f';
+Json._internal.convert['\x10'] = '\\u0010';
+Json._internal.convert['\x11'] = '\\u0011';
+Json._internal.convert['\x12'] = '\\u0012';
+Json._internal.convert['\x13'] = '\\u0013';
+Json._internal.convert['\x14'] = '\\u0014';
+Json._internal.convert['\x15'] = '\\u0015';
+Json._internal.convert['\x16'] = '\\u0016';
+Json._internal.convert['\x17'] = '\\u0017';
+Json._internal.convert['\x18'] = '\\u0018';
+Json._internal.convert['\x19'] = '\\u0019';
+Json._internal.convert['\x1a'] = '\\u001a';
+Json._internal.convert['\x1b'] = '\\u001b';
+Json._internal.convert['\x1c'] = '\\u001c';
+Json._internal.convert['\x1d'] = '\\u001d';
+Json._internal.convert['\x1e'] = '\\u001e';
+Json._internal.convert['\x1f'] = '\\u001f';
+/*
+ * At some point, we probably want to add \x80-\xff as well, and it's then
+ * probably more efficient to generate these strings dynamically.  (Even now
+ * it may be, but this was the the way I started, and so it remains.)
+ */
+
+
+/* Test it */
+libinclude("base.js");
+function testIt()
+{
+    var test = new Object();
+    test.int = 23;
+    test.str = "hello world";
+    test.float = 223.1;
+    test.bool = true;
+    test.array = new Array();
+    test.array[0] = "hello";
+    test.array[1] = "world";
+    test.obj = new Object();
+    test.obj.int = 1000;
+    test.obj.array = new Array();
+    test.obj.array[0] = 42;
+    test.obj.array[1] = 223;
+    printf("%s\n", Json.encode(test));
+}
+//testIt();
+
+%>