r9131: started adding the server side code for "AJAJ" (asynchronous javascript and...
[jelmer/samba4-debian.git] / source / scripting / libjs / encoder.js
1 /*
2         server side js functions for encoding/decoding objects into linear strings
3
4         Copyright Andrew Tridgell 2005
5         released under the GNU GPL Version 2 or later
6 */
7 /*
8         usage:
9
10           enc = encodeObject(obj);
11           obj = decodeObject(enc);
12
13        The encoded format of the object is a string that is safe to
14        use in URLs
15
16        Note that only data elements are encoded, not functions
17 */
18
19 function __count_members(o) {
20         var i, count = 0;
21         for (i in o) { 
22                 count++;  
23         }
24         return count;
25 }
26
27 function __replace(str, old, rep) {
28         var s = string_init();
29         var a = s.split(old, str);
30         var j = s.join(rep, a);
31         return s.join(rep, a);
32 }
33
34 function encodeObject(o) {
35         var s = string_init();
36         var i, r = s.sprintf("%u:", __count_members(o));
37         for (i in o) {
38                 var t = typeof(o[i]);
39                 if (t == 'object' && o[i] == null) {
40                         t = 'null';
41                 }
42                 if (t == 'object') {
43                         r = s.sprintf("%s%s:%s:%s", r, i, t, encodeObject(o[i]));
44                 } else if (t == "string") {
45                         var enc = s.encodeURIComponent(o[i]);
46                         var rep = __replace(enc, '%', '#');
47                         r = s.sprintf("%s%s:%s:%s:", 
48                                       r, i, t, __replace(s.encodeURIComponent(o[i]),'%','#'));
49                 } else if (t == "boolean" || t == "number") {
50                         r = s.sprintf("%s%s:%s:%s:", r, i, t, "" + o[i]);
51                 } else if (t == "undefined" || t == "null") {
52                         r = s.sprintf("%s%s:%s:", r, i, t);
53                 } else {
54                         println("Unable to linearise type " + t);
55                 }
56         }
57         return r;
58 }
59
60 function decodeObjectArray(a) {
61         var s = string_init();
62         var o = new Object();
63         var i, count = a[a.i]; a.i++;
64         for (i=0;i<count;i++) {
65                 var name  = a[a.i]; a.i++;
66                 var type  = a[a.i]; a.i++;
67                 var value;
68                 if (type == 'object') {
69                         o[name] = decodeObjectArray(a);
70                 } else if (type == "string") {
71                         value = s.decodeURIComponent(__replace(a[a.i],'#','%')); a.i++;
72                         o[name] = value;
73                 } else if (type == "boolean") {
74                         value = a[a.i]; a.i++;
75                         if (value == 'true') {
76                                 o[name] = true;
77                         } else {
78                                 o[name] = false;
79                         }
80                 } else if (type == "undefined") {
81                         o[name] = undefined;
82                 } else if (type == "null") {
83                         o[name] = null;
84                 } else if (type == "number") {
85                         value = a[a.i]; a.i++;
86                         o[name] = value + 0;
87                 } else {
88                         println("Unable to delinearise type " + t);
89                         assert(t == "supported type");
90                 }
91         }
92         return o;
93 }
94
95 function decodeObject(str) {
96         var s = string_init();
97         var a = s.split(':', str);
98         a.i = 0;
99         return decodeObjectArray(a);
100 }