source: trunk/prototype/app/plugins/json2/json2.js @ 5283

Revision 5283, 10.7 KB checked in by douglasz, 12 years ago (diff)

Ticket #2402 - Inconsistencia ao anexar mensagens ao e-mail

  • Property svn:executable set to *
Line 
1// origin: http://www.json.org/json2.js
2
3// Create a JSON object only if one does not already exist. We create the
4// methods in a closure to avoid creating global variables.
5
6if (!this.JSON) {
7    this.JSON = {};
8}
9
10(function () {
11
12    function f(n) {
13        // Format integers to have at least two digits.
14        return n < 10 ? '0' + n : n;
15    }
16
17    if (typeof Date.prototype.toJSON !== 'function') {
18
19        Date.prototype.toJSON = function (key) {
20
21            return isFinite(this.valueOf()) ?
22                   this.getUTCFullYear()   + '-' +
23                 f(this.getUTCMonth() + 1) + '-' +
24                 f(this.getUTCDate())      + 'T' +
25                 f(this.getUTCHours())     + ':' +
26                 f(this.getUTCMinutes())   + ':' +
27                 f(this.getUTCSeconds())   + 'Z' : null;
28        };
29
30        String.prototype.toJSON =
31        Number.prototype.toJSON =
32        Boolean.prototype.toJSON = function (key) {
33            return this.valueOf();
34        };
35    }
36
37    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
38        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
39        gap,
40        indent,
41        meta = {    // table of character substitutions
42            '\b': '\\b',
43            '\t': '\\t',
44            '\n': '\\n',
45            '\f': '\\f',
46            '\r': '\\r',
47            '"' : '\\"',
48            '\\': '\\\\'
49        },
50        rep;
51
52
53    function quote(string) {
54
55// If the string contains no control characters, no quote characters, and no
56// backslash characters, then we can safely slap some quotes around it.
57// Otherwise we must also replace the offending characters with safe escape
58// sequences.
59
60        escapable.lastIndex = 0;
61        return escapable.test(string) ?
62            '"' + string.replace(escapable, function (a) {
63                var c = meta[a];
64                return typeof c === 'string' ? c :
65                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
66            }) + '"' :
67            '"' + string + '"';
68    }
69
70
71    function str(key, holder) {
72
73// Produce a string from holder[key].
74
75        var i,          // The loop counter.
76            k,          // The member key.
77            v,          // The member value.
78            length,
79            mind = gap,
80            partial,
81            value = holder[key];
82
83// If the value has a toJSON method, call it to obtain a replacement value.
84
85        if (value && typeof value === 'object' &&
86                typeof value.toJSON === 'function') {
87            value = value.toJSON(key);
88        }
89
90// If we were called with a replacer function, then call the replacer to
91// obtain a replacement value.
92
93        if (typeof rep === 'function') {
94            value = rep.call(holder, key, value);
95        }
96
97// What happens next depends on the value's type.
98
99        switch (typeof value) {
100        case 'string':
101            return quote(value);
102
103        case 'number':
104
105// JSON numbers must be finite. Encode non-finite numbers as null.
106
107            return isFinite(value) ? String(value) : 'null';
108
109        case 'boolean':
110        case 'null':
111
112// If the value is a boolean or null, convert it to a string. Note:
113// typeof null does not produce 'null'. The case is included here in
114// the remote chance that this gets fixed someday.
115
116            return String(value);
117
118// If the type is 'object', we might be dealing with an object or an array or
119// null.
120
121        case 'object':
122
123// Due to a specification blunder in ECMAScript, typeof null is 'object',
124// so watch out for that case.
125
126            if (!value) {
127                return 'null';
128            }
129
130// Make an array to hold the partial results of stringifying this object value.
131
132            gap += indent;
133            partial = [];
134
135// Is the value an array?
136
137            if (Object.prototype.toString.apply(value) === '[object Array]') {
138
139// The value is an array. Stringify every element. Use null as a placeholder
140// for non-JSON values.
141
142                length = value.length;
143                for (i = 0; i < length; i += 1) {
144                    partial[i] = str(i, value) || 'null';
145                }
146
147// Join all of the elements together, separated with commas, and wrap them in
148// brackets.
149
150                v = partial.length === 0 ? '[]' :
151                    gap ? '[\n' + gap +
152                            partial.join(',\n' + gap) + '\n' +
153                                mind + ']' :
154                          '[' + partial.join(',') + ']';
155                gap = mind;
156                return v;
157            }
158
159// If the replacer is an array, use it to select the members to be stringified.
160
161            if (rep && typeof rep === 'object') {
162                length = rep.length;
163                for (i = 0; i < length; i += 1) {
164                    k = rep[i];
165                    if (typeof k === 'string') {
166                        v = str(k, value);
167                        if (v) {
168                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
169                        }
170                    }
171                }
172            } else {
173
174// Otherwise, iterate through all of the keys in the object.
175
176                for (k in value) {
177                    if (Object.hasOwnProperty.call(value, k)) {
178                        v = str(k, value);
179                        if (v) {
180                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
181                        }
182                    }
183                }
184            }
185
186// Join all of the member texts together, separated with commas,
187// and wrap them in braces.
188
189            v = partial.length === 0 ? '{}' :
190                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
191                        mind + '}' : '{' + partial.join(',') + '}';
192            gap = mind;
193            return v;
194        }
195    }
196
197// If the JSON object does not yet have a stringify method, give it one.
198
199    if (typeof JSON.stringify !== 'function') {
200        JSON.stringify = function (value, replacer, space) {
201
202// The stringify method takes a value and an optional replacer, and an optional
203// space parameter, and returns a JSON text. The replacer can be a function
204// that can replace values, or an array of strings that will select the keys.
205// A default replacer method can be provided. Use of the space parameter can
206// produce text that is more easily readable.
207
208            var i;
209            gap = '';
210            indent = '';
211
212// If the space parameter is a number, make an indent string containing that
213// many spaces.
214
215            if (typeof space === 'number') {
216                for (i = 0; i < space; i += 1) {
217                    indent += ' ';
218                }
219
220// If the space parameter is a string, it will be used as the indent string.
221
222            } else if (typeof space === 'string') {
223                indent = space;
224            }
225
226// If there is a replacer, it must be a function or an array.
227// Otherwise, throw an error.
228
229            rep = replacer;
230            if (replacer && typeof replacer !== 'function' &&
231                    (typeof replacer !== 'object' ||
232                     typeof replacer.length !== 'number')) {
233                throw new Error('JSON.stringify');
234            }
235
236// Make a fake root object containing our value under the key of ''.
237// Return the result of stringifying the value.
238
239            return str('', {'': value});
240        };
241    }
242
243
244// If the JSON object does not yet have a parse method, give it one.
245
246    if (typeof JSON.parse !== 'function') {
247        JSON.parse = function (text, reviver) {
248
249// The parse method takes a text and an optional reviver function, and returns
250// a JavaScript value if the text is a valid JSON text.
251
252            var j;
253
254            function walk(holder, key) {
255
256// The walk method is used to recursively walk the resulting structure so
257// that modifications can be made.
258
259                var k, v, value = holder[key];
260                if (value && typeof value === 'object') {
261                    for (k in value) {
262                        if (Object.hasOwnProperty.call(value, k)) {
263                            v = walk(value, k);
264                            if (v !== undefined) {
265                                value[k] = v;
266                            } else {
267                                delete value[k];
268                            }
269                        }
270                    }
271                }
272                return reviver.call(holder, key, value);
273            }
274
275
276// Parsing happens in four stages. In the first stage, we replace certain
277// Unicode characters with escape sequences. JavaScript handles many characters
278// incorrectly, either silently deleting them, or treating them as line endings.
279
280            text = String(text);
281            cx.lastIndex = 0;
282            if (cx.test(text)) {
283                text = text.replace(cx, function (a) {
284                    return '\\u' +
285                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
286                });
287            }
288
289// In the second stage, we run the text against regular expressions that look
290// for non-JSON patterns. We are especially concerned with '()' and 'new'
291// because they can cause invocation, and '=' because it can cause mutation.
292// But just to be safe, we want to reject all unexpected forms.
293
294// We split the second stage into 4 regexp operations in order to work around
295// crippling inefficiencies in IE's and Safari's regexp engines. First we
296// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
297// replace all simple value tokens with ']' characters. Third, we delete all
298// open brackets that follow a colon or comma or that begin the text. Finally,
299// we look to see that the remaining characters are only whitespace or ']' or
300// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
301
302            if (/^[\],:{}\s]*$/
303.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
304.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
305.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
306
307// In the third stage we use the eval function to compile the text into a
308// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
309// in JavaScript: it can begin a block or an object literal. We wrap the text
310// in parens to eliminate the ambiguity.
311
312                j = eval('(' + text + ')');
313
314// In the optional fourth stage, we recursively walk the new structure, passing
315// each name/value pair to a reviver function for possible transformation.
316
317                return typeof reviver === 'function' ?
318                    walk({'': j}, '') : j;
319            }
320
321// If the text is not JSON parseable, then a SyntaxError is thrown.
322
323            throw new SyntaxError('JSON.parse');
324        };
325    }
326}());
Note: See TracBrowser for help on using the repository browser.