]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blob - wradmin_/wradmin/public/yui/json/json-debug.js
Intermediate rename to restructure package.
[philipp/winterrodeln/wradmin.git] / wradmin_ / wradmin / public / yui / json / json-debug.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.7.0
6 */
7 /**
8  * Provides methods to parse JSON strings and convert objects to JSON strings.
9  * @module json
10  * @class JSON
11  * @static
12  */
13 YAHOO.lang.JSON = (function () {
14
15 var l = YAHOO.lang,
16
17     /**
18      * Replace certain Unicode characters that JavaScript may handle incorrectly
19      * during eval--either by deleting them or treating them as line
20      * endings--with escape sequences.
21      * IMPORTANT NOTE: This regex will be used to modify the input if a match is
22      * found.
23      * @property _UNICODE_EXCEPTIONS
24      * @type {RegExp}
25      * @private
26      */
27     _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
28
29     /**
30      * First step in the validation.  Regex used to replace all escape
31      * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
32      * @property _ESCAPES
33      * @type {RegExp}
34      * @static
35      * @private
36      */
37     _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
38
39     /**
40      * Second step in the validation.  Regex used to replace all simple
41      * values with ']' characters.
42      * @property _VALUES
43      * @type {RegExp}
44      * @static
45      * @private
46      */
47     _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
48
49     /**
50      * Third step in the validation.  Regex used to remove all open square
51      * brackets following a colon, comma, or at the beginning of the string.
52      * @property _BRACKETS
53      * @type {RegExp}
54      * @static
55      * @private
56      */
57     _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
58
59     /**
60      * Final step in the validation.  Regex used to test the string left after
61      * all previous replacements for invalid characters.
62      * @property _INVALID
63      * @type {RegExp}
64      * @static
65      * @private
66      */
67     _INVALID  = /^[\],:{}\s]*$/,
68
69     /**
70      * Regex used to replace special characters in strings for JSON
71      * stringification.
72      * @property _SPECIAL_CHARS
73      * @type {RegExp}
74      * @static
75      * @private
76      */
77     _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
78
79     /**
80      * Character substitution map for common escapes and special characters.
81      * @property _CHARS
82      * @type {Object}
83      * @static
84      * @private
85      */
86     _CHARS = {
87         '\b': '\\b',
88         '\t': '\\t',
89         '\n': '\\n',
90         '\f': '\\f',
91         '\r': '\\r',
92         '"' : '\\"',
93         '\\': '\\\\'
94     };
95
96 /**
97  * Traverses nested objects, applying a filter or reviver function to
98  * each value.  The value returned from the function will replace the
99  * original value in the key:value pair.  If the value returned is
100  * undefined, the key will be omitted from the returned object.
101  * @method _revive
102  * @param data {MIXED} Any JavaScript data
103  * @param reviver {Function} filter or mutation function
104  * @return {MIXED} The results of the filtered/mutated data structure
105  * @private
106  */
107 function _revive(data, reviver) {
108     var walk = function (o,key) {
109         var k,v,value = o[key];
110         if (value && typeof value === 'object') {
111             for (k in value) {
112                 if (l.hasOwnProperty(value,k)) {
113                     v = walk(value, k);
114                     if (v === undefined) {
115                         delete value[k];
116                     } else {
117                         value[k] = v;
118                     }
119                 }
120             }
121         }
122         return reviver.call(o,key,value);
123     };
124
125     return typeof reviver === 'function' ? walk({'':data},'') : data;
126 }
127
128 /**
129  * Escapes a special character to a safe Unicode representation
130  * @method _char
131  * @param c {String} single character to escape
132  * @return {String} safe Unicode escape
133  */
134 function _char(c) {
135     if (!_CHARS[c]) {
136         _CHARS[c] =  '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
137     }
138     return _CHARS[c];
139 }
140
141 /**
142  * Replace certain Unicode characters that may be handled incorrectly by
143  * some browser implementations.
144  * @method _prepare
145  * @param s {String} parse input
146  * @return {String} sanitized JSON string ready to be validated/parsed
147  * @private
148  */
149 function _prepare(s) {
150     return s.replace(_UNICODE_EXCEPTIONS, _char);
151 }
152
153 /**
154  * Four step determination whether a string is valid JSON.  In three steps,
155  * escape sequences, safe values, and properly placed open square brackets
156  * are replaced with placeholders or removed.  Then in the final step, the
157  * result of all these replacements is checked for invalid characters.
158  * @method _isValid
159  * @param str {String} JSON string to be tested
160  * @return {boolean} is the string safe for eval?
161  * @static
162  */
163 function _isValid(str) {
164     return l.isString(str) &&
165             _INVALID.test(str.
166             replace(_ESCAPES,'@').
167             replace(_VALUES,']').
168             replace(_BRACKETS,''));
169 }
170
171 /**
172  * Enclose escaped strings in quotes
173  * @method _string
174  * @param s {String} string to wrap
175  * @return {String} '"'+s+'"' after s has had special characters escaped
176  * @private
177  */
178 function _string(s) {
179     return '"' + s.replace(_SPECIAL_CHARS, _char) + '"';
180 }
181
182 /**
183  * Worker function used by public stringify.
184  * @method _stringify
185  * @param h {Object} object holding the key
186  * @param key {String} String key in object h to serialize
187  * @param depth {Number} depth to serialize
188  * @param w {Array|Function} array of whitelisted keys OR replacer function
189  * @param pstack {Array} used to protect against recursion
190  * @return {String} serialized version of o
191  */
192 function _stringify(h,key,d,w,pstack) {
193     var o = typeof w === 'function' ? w.call(h,key,h[key]) : h[key],
194         i,len,j, // array iteration
195         k,v,     // object iteration
196         isArray, // forking in typeof 'object'
197         a;       // composition array for performance over string concat
198
199     if (o instanceof Date) {
200         o = l.JSON.dateToString(o);
201     } else if (o instanceof String || o instanceof Boolean || o instanceof Number) {
202         o = o.valueOf();
203     }
204
205     switch (typeof o) {
206         case 'string' : return _string(o);
207         case 'number' : return isFinite(o) ? String(o) : 'null';
208         case 'boolean': return String(o);
209         case 'object' :
210             // null
211             if (o === null) {
212                 return 'null';
213             }
214
215             // Check for cyclical references
216             for (i = pstack.length - 1; i >= 0; --i) {
217                 if (pstack[i] === o) {
218                     return 'null';
219                 }
220             }
221
222             // Add the object to the processing stack
223             pstack[pstack.length] = o;
224
225             a = [];
226             isArray = l.isArray(o);
227
228             // Only recurse if we're above depth config
229             if (d > 0) {
230                 // Array
231                 if (isArray) {
232                     for (i = o.length - 1; i >= 0; --i) {
233                         a[i] = _stringify(o,i,d-1,w,pstack) || 'null';
234                     }
235
236                 // Object
237                 } else {
238                     j = 0;
239                     // Use whitelist keys if provided as an array
240                     if (l.isArray(w)) {
241                         for (i = 0, len = w.length; i < len; ++i) {
242                             k = w[i];
243                             v = _stringify(o,k,d-1,w,pstack);
244                             if (v) {
245                                 a[j++] = _string(k) + ':' + v;
246                             }
247                         }
248                     } else {
249                         for (k in o) {
250                             if (typeof k === 'string' && l.hasOwnProperty(o,k)) {
251                                 v = _stringify(o,k,d-1,w,pstack);
252                                 if (v) {
253                                     a[j++] = _string(k) + ':' + v;
254                                 }
255                             }
256                         }
257                     }
258
259                     // sort object keys for easier readability
260                     a.sort();
261                 }
262             }
263
264             // remove the object from the stack
265             pstack.pop();
266
267             return isArray ? '['+a.join(',')+']' : '{'+a.join(',')+'}';
268     }
269
270     return undefined; // invalid input
271 }
272
273 // Return the public API
274 return {
275     /**
276      * Four step determination whether a string is valid JSON.  In three steps,
277      * escape sequences, safe values, and properly placed open square brackets
278      * are replaced with placeholders or removed.  Then in the final step, the
279      * result of all these replacements is checked for invalid characters.
280      * @method isValid
281      * @param str {String} JSON string to be tested
282      * @return {boolean} is the string safe for eval?
283      * @static
284      */
285     isValid : function (s) {
286         return _isValid(_prepare(s));
287     },
288
289     /**
290      * Parse a JSON string, returning the native JavaScript representation.
291      * Only minor modifications from http://www.json.org/json2.js.
292      * @param s {string} JSON string data
293      * @param reviver {function} (optional) function(k,v) passed each key:value
294      *          pair of object literals, allowing pruning or altering values
295      * @return {MIXED} the native JavaScript representation of the JSON string
296      * @throws SyntaxError
297      * @method parse
298      * @static
299      */
300     parse : function (s,reviver) {
301         // sanitize
302         s = _prepare(s);
303
304         // Ensure valid JSON
305         if (_isValid(s)) {
306             // Eval the text into a JavaScript data structure, apply the
307             // reviver function if provided, and return
308             return _revive( eval('(' + s + ')'), reviver );
309         }
310
311         // The text is not valid JSON
312         throw new SyntaxError('parseJSON');
313     },
314
315     /**
316      * Converts an arbitrary value to a JSON string representation.
317      * Cyclical object or array references are replaced with null.
318      * If a whitelist is provided, only matching object keys will be included.
319      * If a depth limit is provided, objects and arrays at that depth will
320      * be stringified as empty.
321      * @method stringify
322      * @param o {MIXED} any arbitrary object to convert to JSON string
323      * @param w {Array|Function} (optional) whitelist of acceptable object keys to include OR a function(value,key) to alter values before serialization
324      * @param d {number} (optional) depth limit to recurse objects/arrays (practical minimum 1)
325      * @return {string} JSON string representation of the input
326      * @static
327      */
328     stringify : function (o,w,d) {
329         if (o !== undefined) {
330             // Ensure whitelist keys are unique (bug 2110391)
331             if (l.isArray(w)) {
332                 w = (function (a) {
333                     var uniq=[],map={},v,i,j,len;
334                     for (i=0,j=0,len=a.length; i<len; ++i) {
335                         v = a[i];
336                         if (typeof v === 'string' && map[v] === undefined) {
337                             uniq[(map[v] = j++)] = v;
338                         }
339                     }
340                     return uniq;
341                 })(w);
342             }
343
344             // Default depth to POSITIVE_INFINITY
345             d = d >= 0 ? d : 1/0;
346
347             // process the input
348             return _stringify({'':o},'',d,w,[]);
349         }
350
351         return undefined;
352     },
353
354     /**
355      * Serializes a Date instance as a UTC date string.  Used internally by
356      * stringify.  Override this method if you need Dates serialized in a
357      * different format.
358      * @method dateToString
359      * @param d {Date} The Date to serialize
360      * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
361      * @static
362      */
363     dateToString : function (d) {
364         function _zeroPad(v) {
365             return v < 10 ? '0' + v : v;
366         }
367
368         return d.getUTCFullYear()         + '-' +
369             _zeroPad(d.getUTCMonth() + 1) + '-' +
370             _zeroPad(d.getUTCDate())      + 'T' +
371             _zeroPad(d.getUTCHours())     + ':' +
372             _zeroPad(d.getUTCMinutes())   + ':' +
373             _zeroPad(d.getUTCSeconds())   + 'Z';
374     },
375
376     /**
377      * Reconstitute Date instances from the default JSON UTC serialization.
378      * Reference this from a reviver function to rebuild Dates during the
379      * parse operation.
380      * @method stringToDate
381      * @param str {String} String serialization of a Date
382      * @return {Date}
383      */
384     stringToDate : function (str) {
385         if (/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/.test(str)) {
386             var d = new Date();
387             d.setUTCFullYear(RegExp.$1, (RegExp.$2|0)-1, RegExp.$3);
388             d.setUTCHours(RegExp.$4, RegExp.$5, RegExp.$6);
389             return d;
390         }
391         return str;
392     }
393 };
394
395 })();
396 YAHOO.register("json", YAHOO.lang.JSON, {version: "2.7.0", build: "1799"});