archrelease: copy trunk to extra-x86_64
[arch-packages.git] / seed / trunk / GLib.js
blob5aec39a73ba2fb98f061fc331e86c433ce2fa19b
1 GLib = imports.gi.GLib;
3 (function() {
5 /* Variant Sugar 
6  * Provide commodities methods to convert Variant from/to javascript object.
7  * variant.toJS() : returns a javascript object representing the Variant 
8  # @variant
9  * Variant.new(signature, value): returns a GVariant structure representing
10  * the javascript object @value
11  *
12  * This implementation uses json-glib's json <-> variant conversion facilities
13  * if presents and fallback to a javascript implementation otherwise.
14  * This javascript implementation is imported from gjs with modification for
15  * JSCore compatibility (Copyright 2011 Giovanni Campagna,
16  * see gjs/override/GLib.js for licence)
17  */
19     // Use json-glib's json <-> variant conversion if present.
20     // Defaults to javascript code imported from gjs otherwise.
21     GLib.Variant.prototype.to_js = function(signature) {
22         return _toJS(signature, this);
23     }
24     var toVariant = _toVariant;
25     
26     try {
27         JSONGLib = imports.gi.Json;
28     }
29     catch (e) {}
31     if (JSONGLib && JSONGLib.gvariant_serialize_data)
32     {
33         GLib.Variant.prototype.to_js = function(signature) {
34             return _toJSNative(signature, this);
35         }
36         toVariant = _toVariantNative;
37     }
39     GLib.Variant.new = function (value, sig) {
40         var signature = Array.prototype.slice.call(sig);
42         if (signature.length != 0)
43             throw new TypeError('Invalid GVariant signature (more than one single complete type)');
44         var variant = toVariant(signature, value);
45         return variant;
46     }
48     GLib.Variant.prototype.toString = function() {
49         return '[object variant of type "' + this.get_type_string() + '"]';
50     };
52 /// End Variant Sugar ///
53 }).apply();
55 function _toVariantNative(signature, object)
57     if (!object || object == '')
58         return null;
59     if (!signature || signature == '')
60         signature = null;
62     return JSONGLib.gvariant_deserialize_data (JSON.stringify (object),
63                                                        -1, signature);
66 function _toJSNative(signature, variant)
68     if (!variant)
69         return;
71     var jsonStr = JSONGLib.gvariant_serialize_data (variant, signature);
72     if (!jsonStr)
73         return;
75     return JSON.parse (jsonStr);
78 // Code imported from gjs, modified for JSCore idoms.
79 // Copyright 2011 Giovanni Campagna (see gjs/override/GLib.js for licence)
81 const SIMPLE_TYPES = ['b', 'y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd', 's', 'o', 'g'];
83 function _read_single_type(signature, forceSimple) {
84     var char = signature.shift();
85     var isSimple = false;
87     if (SIMPLE_TYPES.indexOf(char) == -1) {
88         if (forceSimple)
89             throw new TypeError('Invalid GVariant signature (a simple type was expected)');
90     } else
91         isSimple = true;
93     if (char == 'm' || char == 'a')
94         return [char].concat(_read_single_type(signature, false));
95     if (char == '{') {
96         var key = _read_single_type(signature, true);
97         var val = _read_single_type(signature, false);
98         var close = signature.shift();
99         if (close != '}')
100             throw new TypeError('Invalid GVariant signature for type DICT_ENTRY (expected "}"');
101         return [char].concat(key, val, close);
102     }
103     if (char == '(') {
104         var res = [char];
105         while (true) {
106             if (signature.length == 0)
107                 throw new TypeError('Invalid GVariant signature for type TUPLE (expected ")")');
108             var next = signature[0];
109             if (next == ')') {
110                 signature.shift();
111                 return res.concat(next);
112             }
113             var el = _read_single_type(signature);
114             res = res.concat(el);
115         }
116     }
118     // Valid types are simple types, arrays, maybes, tuples, dictionary entries and variants
119     if (!isSimple && char != 'v')
120         throw new TypeError('Invalid GVariant signature (' + char + ' is not a valid type)');
122     return [char];
126 function _toVariant(signature, value) {
127     if (signature.length == 0)
128             throw new TypeError('GVariant signature cannot be empty');
130     var char = signature.shift();
131     switch (char) {
132     case 'b':
133         return GLib.Variant.new_boolean(value);
134     case 'y':
135         return GLib.Variant.new_byte(value);
136     case 'n':
137         return GLib.Variant.new_int16(value);
138     case 'q':
139         return GLib.Variant.new_uint16(value);
140     case 'i':
141         return GLib.Variant.new_int32(value);
142     case 'u':
143         return GLib.Variant.new_uint32(value);
144     case 'x':
145         return GLib.Variant.new_int64(value);
146     case 't':
147         return GLib.Variant.new_uint64(value);
148     case 'h':
149         return GLib.Variant.new_handle(value);
150     case 'd':
151         return GLib.Variant.new_double(value);
152     case 's':
153         return GLib.Variant.new_string(value);
154     case 'o':
155         return GLib.Variant.new_object_path(value);
156     case 'g':
157         return GLib.Variant.new_signature(value);
158     case 'v':
159         return GLib.Variant.new_variant(value);
160     case 'm':
161         if (value != null)
162             return GLib.Variant.new_maybe(null, _pack_variant(signature, value))
163         else
164             return GLib.Variant.new_maybe(GLib.VariantType.new(_read_single_type(signature, false).join('')), null);
165     case 'a':
166         var arrayType = _read_single_type(signature, false);
167         if (arrayType[0] == 's') {
168             // special case for array of strings
169             return GLib.Variant.new_strv(value, value.length);
170         }
171         if (arrayType[0] == 'y') {
172             // special case for array of bytes
173             return GLib.Variant.new_bytestring(value);
174         }
175         if (arrayType[0] == 'a' && arrayType[1] == 'y') {
176             // special case for array of array of bytes
177             return GLib.Variant.new_bytestring_array(value, value.length);
178         }
180         var arrayValue = [];
181         if (arrayType[0] == '{') {
182             // special case for dictionaries
183             for (var key in value) {
184                 var copy = [].concat(arrayType);
185                 var child = _pack_variant(copy, [key, value[key]]);
186                 arrayValue.push(child);
187             }
188         } else {
189             for (var i = 0; i < value.length; i++) {
190                 var copy = [].concat(arrayType);
191                 var child = _pack_variant(copy, value[i]);
192                 arrayValue.push(child);
193             }
194         }
195         return GLib.Variant.new_array(GLib.VariantType.new(arrayType.join('')), arrayValue, arrayValue.length);
196     case '(':
197         var children = [ ];
198         for (var i = 0; i < value.length; i++) {
199             var next = signature[0];
200             if (next == ')')
201                 break;
202             children.push(_pack_variant(signature, value[i]));
203         }
205         if (signature[0] != ')')
206             throw new TypeError('Invalid GVariant signature for type TUPLE (expected ")")');
207         signature.shift();
208         return GLib.Variant.new_tuple(children, children.length);
209     case '{':
210         var key = _pack_variant(signature, value[0]);
211         var child = _pack_variant(signature, value[1]);
213         if (signature[0] != '}')
214             throw new TypeError('Invalid GVariant signature for type DICT_ENTRY (expected "}")');
215         signature.shift();
217         return GLib.Variant.new_dict_entry(key, child);
218     default:
219         throw new TypeError('Invalid GVariant signature (unexpected character ' + char + ')');
220     }
223 function _toJS(signature, variant) {
224     switch (String.fromCharCode(variant.classify())) {
225     case 'b':
226         return variant.get_boolean();
227     case 'y':
228         return variant.get_byte();
229     case 'n':
230         return variant.get_int16();
231     case 'q':
232         return variant.get_uint16();
233     case 'i':
234         return variant.get_int32();
235     case 'u':
236         return variant.get_uint32();
237     case 'x':
238         return variant.get_int64();
239     case 't':
240         return variant.get_uint64();
241     case 'h':
242         return variant.get_handle();
243     case 'd':
244         return variant.get_double();
245     case 'o':
246     case 'g':
247     case 's':
248         // g_variant_get_string has length as out argument
249         return variant.get_string();
250     case 'v':
251         return variant.get_variant();
252     case 'm':
253         var val = variant.get_maybe();
254         return _toJS(val);
255     case 'a':
256         if (variant.is_container()) {
257             // special case containers
258             var ret = { };
259             var nElements = variant.n_children();
260             for (var i = 0; i < nElements; i++) {
261                 // always unpack the dictionary entry, and always unpack
262                 // the key (or it cannot be added as a key)
263                 var val = _toJS(variant.get_child_value(i));
264                 var key = val[0].classify ? _toJS(val[0]) : val[0];
265                 ret[key] = val[1] && val[1].classify ? _toJS(val[1]) : val[1]
266             }
267             return ret;
268         }
269         // fall through
270     case '(':
271     case '{':
272         var ret = [ ];
273         var nElements = variant.n_children();
274         for (var i = 0; i < nElements; i++) {
275             var val = variant.get_child_value(i);
276             ret.push(_toJS(val));
277         }
278         return ret;
279     }
281     throw new Error('Assertion failure: this code should not be reached');