~ubuntu-branches/ubuntu/natty/otrs2/natty-updates

« back to all changes in this revision

Viewing changes to var/httpd/htdocs/yui/2.7.0/build/json/json.js

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2010-08-09 19:43:44 UTC
  • mfrom: (1.1.12)
  • Revision ID: package-import@ubuntu.com-20100809194344-absef1ut5mfj3qhv
Tags: 2.4.7+dfsg1-1
* Strip out yui from the source in the dfsg version.
  Closes: #591196
* Depend on libjs-yui and link to this package, instead of using the embedded
  yui version. This changes make the flash ticket statistics unuseable!
  Closes: #592146

Show diffs side-by-side

added added

removed removed

Lines of Context:
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"});