Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / static / snf / js / lib / json2.js @ 6de7fde5

History | View | Annotate | Download (17 kB)

1 8d08f18a Kostas Papadimitriou
/*
2 8d08f18a Kostas Papadimitriou
    http://www.JSON.org/json2.js
3 8d08f18a Kostas Papadimitriou
    2011-02-23
4 8d08f18a Kostas Papadimitriou

5 8d08f18a Kostas Papadimitriou
    Public Domain.
6 8d08f18a Kostas Papadimitriou

7 8d08f18a Kostas Papadimitriou
    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
8 8d08f18a Kostas Papadimitriou

9 8d08f18a Kostas Papadimitriou
    See http://www.JSON.org/js.html
10 8d08f18a Kostas Papadimitriou

11 8d08f18a Kostas Papadimitriou

12 8d08f18a Kostas Papadimitriou
    This code should be minified before deployment.
13 8d08f18a Kostas Papadimitriou
    See http://javascript.crockford.com/jsmin.html
14 8d08f18a Kostas Papadimitriou

15 8d08f18a Kostas Papadimitriou
    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
16 8d08f18a Kostas Papadimitriou
    NOT CONTROL.
17 8d08f18a Kostas Papadimitriou

18 8d08f18a Kostas Papadimitriou

19 8d08f18a Kostas Papadimitriou
    This file creates a global JSON object containing two methods: stringify
20 8d08f18a Kostas Papadimitriou
    and parse.
21 8d08f18a Kostas Papadimitriou

22 8d08f18a Kostas Papadimitriou
        JSON.stringify(value, replacer, space)
23 8d08f18a Kostas Papadimitriou
            value       any JavaScript value, usually an object or array.
24 8d08f18a Kostas Papadimitriou

25 8d08f18a Kostas Papadimitriou
            replacer    an optional parameter that determines how object
26 8d08f18a Kostas Papadimitriou
                        values are stringified for objects. It can be a
27 8d08f18a Kostas Papadimitriou
                        function or an array of strings.
28 8d08f18a Kostas Papadimitriou

29 8d08f18a Kostas Papadimitriou
            space       an optional parameter that specifies the indentation
30 8d08f18a Kostas Papadimitriou
                        of nested structures. If it is omitted, the text will
31 8d08f18a Kostas Papadimitriou
                        be packed without extra whitespace. If it is a number,
32 8d08f18a Kostas Papadimitriou
                        it will specify the number of spaces to indent at each
33 8d08f18a Kostas Papadimitriou
                        level. If it is a string (such as '\t' or ' '),
34 8d08f18a Kostas Papadimitriou
                        it contains the characters used to indent at each level.
35 8d08f18a Kostas Papadimitriou

36 8d08f18a Kostas Papadimitriou
            This method produces a JSON text from a JavaScript value.
37 8d08f18a Kostas Papadimitriou

38 8d08f18a Kostas Papadimitriou
            When an object value is found, if the object contains a toJSON
39 8d08f18a Kostas Papadimitriou
            method, its toJSON method will be called and the result will be
40 8d08f18a Kostas Papadimitriou
            stringified. A toJSON method does not serialize: it returns the
41 8d08f18a Kostas Papadimitriou
            value represented by the name/value pair that should be serialized,
42 8d08f18a Kostas Papadimitriou
            or undefined if nothing should be serialized. The toJSON method
43 8d08f18a Kostas Papadimitriou
            will be passed the key associated with the value, and this will be
44 8d08f18a Kostas Papadimitriou
            bound to the value
45 8d08f18a Kostas Papadimitriou

46 8d08f18a Kostas Papadimitriou
            For example, this would serialize Dates as ISO strings.
47 8d08f18a Kostas Papadimitriou

48 8d08f18a Kostas Papadimitriou
                Date.prototype.toJSON = function (key) {
49 8d08f18a Kostas Papadimitriou
                    function f(n) {
50 8d08f18a Kostas Papadimitriou
                        // Format integers to have at least two digits.
51 8d08f18a Kostas Papadimitriou
                        return n < 10 ? '0' + n : n;
52 8d08f18a Kostas Papadimitriou
                    }
53 8d08f18a Kostas Papadimitriou

54 8d08f18a Kostas Papadimitriou
                    return this.getUTCFullYear()   + '-' +
55 8d08f18a Kostas Papadimitriou
                         f(this.getUTCMonth() + 1) + '-' +
56 8d08f18a Kostas Papadimitriou
                         f(this.getUTCDate())      + 'T' +
57 8d08f18a Kostas Papadimitriou
                         f(this.getUTCHours())     + ':' +
58 8d08f18a Kostas Papadimitriou
                         f(this.getUTCMinutes())   + ':' +
59 8d08f18a Kostas Papadimitriou
                         f(this.getUTCSeconds())   + 'Z';
60 8d08f18a Kostas Papadimitriou
                };
61 8d08f18a Kostas Papadimitriou

62 8d08f18a Kostas Papadimitriou
            You can provide an optional replacer method. It will be passed the
63 8d08f18a Kostas Papadimitriou
            key and value of each member, with this bound to the containing
64 8d08f18a Kostas Papadimitriou
            object. The value that is returned from your method will be
65 8d08f18a Kostas Papadimitriou
            serialized. If your method returns undefined, then the member will
66 8d08f18a Kostas Papadimitriou
            be excluded from the serialization.
67 8d08f18a Kostas Papadimitriou

68 8d08f18a Kostas Papadimitriou
            If the replacer parameter is an array of strings, then it will be
69 8d08f18a Kostas Papadimitriou
            used to select the members to be serialized. It filters the results
70 8d08f18a Kostas Papadimitriou
            such that only members with keys listed in the replacer array are
71 8d08f18a Kostas Papadimitriou
            stringified.
72 8d08f18a Kostas Papadimitriou

73 8d08f18a Kostas Papadimitriou
            Values that do not have JSON representations, such as undefined or
74 8d08f18a Kostas Papadimitriou
            functions, will not be serialized. Such values in objects will be
75 8d08f18a Kostas Papadimitriou
            dropped; in arrays they will be replaced with null. You can use
76 8d08f18a Kostas Papadimitriou
            a replacer function to replace those with JSON values.
77 8d08f18a Kostas Papadimitriou
            JSON.stringify(undefined) returns undefined.
78 8d08f18a Kostas Papadimitriou

79 8d08f18a Kostas Papadimitriou
            The optional space parameter produces a stringification of the
80 8d08f18a Kostas Papadimitriou
            value that is filled with line breaks and indentation to make it
81 8d08f18a Kostas Papadimitriou
            easier to read.
82 8d08f18a Kostas Papadimitriou

83 8d08f18a Kostas Papadimitriou
            If the space parameter is a non-empty string, then that string will
84 8d08f18a Kostas Papadimitriou
            be used for indentation. If the space parameter is a number, then
85 8d08f18a Kostas Papadimitriou
            the indentation will be that many spaces.
86 8d08f18a Kostas Papadimitriou

87 8d08f18a Kostas Papadimitriou
            Example:
88 8d08f18a Kostas Papadimitriou

89 8d08f18a Kostas Papadimitriou
            text = JSON.stringify(['e', {pluribus: 'unum'}]);
90 8d08f18a Kostas Papadimitriou
            // text is '["e",{"pluribus":"unum"}]'
91 8d08f18a Kostas Papadimitriou

92 8d08f18a Kostas Papadimitriou

93 8d08f18a Kostas Papadimitriou
            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
94 8d08f18a Kostas Papadimitriou
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
95 8d08f18a Kostas Papadimitriou

96 8d08f18a Kostas Papadimitriou
            text = JSON.stringify([new Date()], function (key, value) {
97 8d08f18a Kostas Papadimitriou
                return this[key] instanceof Date ?
98 8d08f18a Kostas Papadimitriou
                    'Date(' + this[key] + ')' : value;
99 8d08f18a Kostas Papadimitriou
            });
100 8d08f18a Kostas Papadimitriou
            // text is '["Date(---current time---)"]'
101 8d08f18a Kostas Papadimitriou

102 8d08f18a Kostas Papadimitriou

103 8d08f18a Kostas Papadimitriou
        JSON.parse(text, reviver)
104 8d08f18a Kostas Papadimitriou
            This method parses a JSON text to produce an object or array.
105 8d08f18a Kostas Papadimitriou
            It can throw a SyntaxError exception.
106 8d08f18a Kostas Papadimitriou

107 8d08f18a Kostas Papadimitriou
            The optional reviver parameter is a function that can filter and
108 8d08f18a Kostas Papadimitriou
            transform the results. It receives each of the keys and values,
109 8d08f18a Kostas Papadimitriou
            and its return value is used instead of the original value.
110 8d08f18a Kostas Papadimitriou
            If it returns what it received, then the structure is not modified.
111 8d08f18a Kostas Papadimitriou
            If it returns undefined then the member is deleted.
112 8d08f18a Kostas Papadimitriou

113 8d08f18a Kostas Papadimitriou
            Example:
114 8d08f18a Kostas Papadimitriou

115 8d08f18a Kostas Papadimitriou
            // Parse the text. Values that look like ISO date strings will
116 8d08f18a Kostas Papadimitriou
            // be converted to Date objects.
117 8d08f18a Kostas Papadimitriou

118 8d08f18a Kostas Papadimitriou
            myData = JSON.parse(text, function (key, value) {
119 8d08f18a Kostas Papadimitriou
                var a;
120 8d08f18a Kostas Papadimitriou
                if (typeof value === 'string') {
121 8d08f18a Kostas Papadimitriou
                    a =
122 8d08f18a Kostas Papadimitriou
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
123 8d08f18a Kostas Papadimitriou
                    if (a) {
124 8d08f18a Kostas Papadimitriou
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
125 8d08f18a Kostas Papadimitriou
                            +a[5], +a[6]));
126 8d08f18a Kostas Papadimitriou
                    }
127 8d08f18a Kostas Papadimitriou
                }
128 8d08f18a Kostas Papadimitriou
                return value;
129 8d08f18a Kostas Papadimitriou
            });
130 8d08f18a Kostas Papadimitriou

131 8d08f18a Kostas Papadimitriou
            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
132 8d08f18a Kostas Papadimitriou
                var d;
133 8d08f18a Kostas Papadimitriou
                if (typeof value === 'string' &&
134 8d08f18a Kostas Papadimitriou
                        value.slice(0, 5) === 'Date(' &&
135 8d08f18a Kostas Papadimitriou
                        value.slice(-1) === ')') {
136 8d08f18a Kostas Papadimitriou
                    d = new Date(value.slice(5, -1));
137 8d08f18a Kostas Papadimitriou
                    if (d) {
138 8d08f18a Kostas Papadimitriou
                        return d;
139 8d08f18a Kostas Papadimitriou
                    }
140 8d08f18a Kostas Papadimitriou
                }
141 8d08f18a Kostas Papadimitriou
                return value;
142 8d08f18a Kostas Papadimitriou
            });
143 8d08f18a Kostas Papadimitriou

144 8d08f18a Kostas Papadimitriou

145 8d08f18a Kostas Papadimitriou
    This is a reference implementation. You are free to copy, modify, or
146 8d08f18a Kostas Papadimitriou
    redistribute.
147 8d08f18a Kostas Papadimitriou
*/
148 8d08f18a Kostas Papadimitriou
149 8d08f18a Kostas Papadimitriou
/*jslint evil: true, strict: false, regexp: false */
150 8d08f18a Kostas Papadimitriou
151 8d08f18a Kostas Papadimitriou
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
152 8d08f18a Kostas Papadimitriou
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
153 8d08f18a Kostas Papadimitriou
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
154 8d08f18a Kostas Papadimitriou
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
155 8d08f18a Kostas Papadimitriou
    test, toJSON, toString, valueOf
156 8d08f18a Kostas Papadimitriou
*/
157 8d08f18a Kostas Papadimitriou
158 8d08f18a Kostas Papadimitriou
159 8d08f18a Kostas Papadimitriou
// Create a JSON object only if one does not already exist. We create the
160 8d08f18a Kostas Papadimitriou
// methods in a closure to avoid creating global variables.
161 8d08f18a Kostas Papadimitriou
162 8d08f18a Kostas Papadimitriou
var JSON;
163 8d08f18a Kostas Papadimitriou
if (!JSON) {
164 8d08f18a Kostas Papadimitriou
    JSON = {};
165 8d08f18a Kostas Papadimitriou
}
166 8d08f18a Kostas Papadimitriou
167 8d08f18a Kostas Papadimitriou
(function () {
168 8d08f18a Kostas Papadimitriou
    "use strict";
169 8d08f18a Kostas Papadimitriou
170 8d08f18a Kostas Papadimitriou
    function f(n) {
171 8d08f18a Kostas Papadimitriou
        // Format integers to have at least two digits.
172 8d08f18a Kostas Papadimitriou
        return n < 10 ? '0' + n : n;
173 8d08f18a Kostas Papadimitriou
    }
174 8d08f18a Kostas Papadimitriou
175 8d08f18a Kostas Papadimitriou
    if (typeof Date.prototype.toJSON !== 'function') {
176 8d08f18a Kostas Papadimitriou
177 8d08f18a Kostas Papadimitriou
        Date.prototype.toJSON = function (key) {
178 8d08f18a Kostas Papadimitriou
179 8d08f18a Kostas Papadimitriou
            return isFinite(this.valueOf()) ?
180 8d08f18a Kostas Papadimitriou
                this.getUTCFullYear()     + '-' +
181 8d08f18a Kostas Papadimitriou
                f(this.getUTCMonth() + 1) + '-' +
182 8d08f18a Kostas Papadimitriou
                f(this.getUTCDate())      + 'T' +
183 8d08f18a Kostas Papadimitriou
                f(this.getUTCHours())     + ':' +
184 8d08f18a Kostas Papadimitriou
                f(this.getUTCMinutes())   + ':' +
185 8d08f18a Kostas Papadimitriou
                f(this.getUTCSeconds())   + 'Z' : null;
186 8d08f18a Kostas Papadimitriou
        };
187 8d08f18a Kostas Papadimitriou
188 8d08f18a Kostas Papadimitriou
        String.prototype.toJSON      =
189 8d08f18a Kostas Papadimitriou
            Number.prototype.toJSON  =
190 8d08f18a Kostas Papadimitriou
            Boolean.prototype.toJSON = function (key) {
191 8d08f18a Kostas Papadimitriou
                return this.valueOf();
192 8d08f18a Kostas Papadimitriou
            };
193 8d08f18a Kostas Papadimitriou
    }
194 8d08f18a Kostas Papadimitriou
195 8d08f18a Kostas Papadimitriou
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
196 8d08f18a Kostas Papadimitriou
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
197 8d08f18a Kostas Papadimitriou
        gap,
198 8d08f18a Kostas Papadimitriou
        indent,
199 8d08f18a Kostas Papadimitriou
        meta = {    // table of character substitutions
200 8d08f18a Kostas Papadimitriou
            '\b': '\\b',
201 8d08f18a Kostas Papadimitriou
            '\t': '\\t',
202 8d08f18a Kostas Papadimitriou
            '\n': '\\n',
203 8d08f18a Kostas Papadimitriou
            '\f': '\\f',
204 8d08f18a Kostas Papadimitriou
            '\r': '\\r',
205 8d08f18a Kostas Papadimitriou
            '"' : '\\"',
206 8d08f18a Kostas Papadimitriou
            '\\': '\\\\'
207 8d08f18a Kostas Papadimitriou
        },
208 8d08f18a Kostas Papadimitriou
        rep;
209 8d08f18a Kostas Papadimitriou
210 8d08f18a Kostas Papadimitriou
211 8d08f18a Kostas Papadimitriou
    function quote(string) {
212 8d08f18a Kostas Papadimitriou
213 8d08f18a Kostas Papadimitriou
// If the string contains no control characters, no quote characters, and no
214 8d08f18a Kostas Papadimitriou
// backslash characters, then we can safely slap some quotes around it.
215 8d08f18a Kostas Papadimitriou
// Otherwise we must also replace the offending characters with safe escape
216 8d08f18a Kostas Papadimitriou
// sequences.
217 8d08f18a Kostas Papadimitriou
218 8d08f18a Kostas Papadimitriou
        escapable.lastIndex = 0;
219 8d08f18a Kostas Papadimitriou
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
220 8d08f18a Kostas Papadimitriou
            var c = meta[a];
221 8d08f18a Kostas Papadimitriou
            return typeof c === 'string' ? c :
222 8d08f18a Kostas Papadimitriou
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
223 8d08f18a Kostas Papadimitriou
        }) + '"' : '"' + string + '"';
224 8d08f18a Kostas Papadimitriou
    }
225 8d08f18a Kostas Papadimitriou
226 8d08f18a Kostas Papadimitriou
227 8d08f18a Kostas Papadimitriou
    function str(key, holder) {
228 8d08f18a Kostas Papadimitriou
229 8d08f18a Kostas Papadimitriou
// Produce a string from holder[key].
230 8d08f18a Kostas Papadimitriou
231 8d08f18a Kostas Papadimitriou
        var i,          // The loop counter.
232 8d08f18a Kostas Papadimitriou
            k,          // The member key.
233 8d08f18a Kostas Papadimitriou
            v,          // The member value.
234 8d08f18a Kostas Papadimitriou
            length,
235 8d08f18a Kostas Papadimitriou
            mind = gap,
236 8d08f18a Kostas Papadimitriou
            partial,
237 8d08f18a Kostas Papadimitriou
            value = holder[key];
238 8d08f18a Kostas Papadimitriou
239 8d08f18a Kostas Papadimitriou
// If the value has a toJSON method, call it to obtain a replacement value.
240 8d08f18a Kostas Papadimitriou
241 8d08f18a Kostas Papadimitriou
        if (value && typeof value === 'object' &&
242 8d08f18a Kostas Papadimitriou
                typeof value.toJSON === 'function') {
243 8d08f18a Kostas Papadimitriou
            value = value.toJSON(key);
244 8d08f18a Kostas Papadimitriou
        }
245 8d08f18a Kostas Papadimitriou
246 8d08f18a Kostas Papadimitriou
// If we were called with a replacer function, then call the replacer to
247 8d08f18a Kostas Papadimitriou
// obtain a replacement value.
248 8d08f18a Kostas Papadimitriou
249 8d08f18a Kostas Papadimitriou
        if (typeof rep === 'function') {
250 8d08f18a Kostas Papadimitriou
            value = rep.call(holder, key, value);
251 8d08f18a Kostas Papadimitriou
        }
252 8d08f18a Kostas Papadimitriou
253 8d08f18a Kostas Papadimitriou
// What happens next depends on the value's type.
254 8d08f18a Kostas Papadimitriou
255 8d08f18a Kostas Papadimitriou
        switch (typeof value) {
256 8d08f18a Kostas Papadimitriou
        case 'string':
257 8d08f18a Kostas Papadimitriou
            return quote(value);
258 8d08f18a Kostas Papadimitriou
259 8d08f18a Kostas Papadimitriou
        case 'number':
260 8d08f18a Kostas Papadimitriou
261 8d08f18a Kostas Papadimitriou
// JSON numbers must be finite. Encode non-finite numbers as null.
262 8d08f18a Kostas Papadimitriou
263 8d08f18a Kostas Papadimitriou
            return isFinite(value) ? String(value) : 'null';
264 8d08f18a Kostas Papadimitriou
265 8d08f18a Kostas Papadimitriou
        case 'boolean':
266 8d08f18a Kostas Papadimitriou
        case 'null':
267 8d08f18a Kostas Papadimitriou
268 8d08f18a Kostas Papadimitriou
// If the value is a boolean or null, convert it to a string. Note:
269 8d08f18a Kostas Papadimitriou
// typeof null does not produce 'null'. The case is included here in
270 8d08f18a Kostas Papadimitriou
// the remote chance that this gets fixed someday.
271 8d08f18a Kostas Papadimitriou
272 8d08f18a Kostas Papadimitriou
            return String(value);
273 8d08f18a Kostas Papadimitriou
274 8d08f18a Kostas Papadimitriou
// If the type is 'object', we might be dealing with an object or an array or
275 8d08f18a Kostas Papadimitriou
// null.
276 8d08f18a Kostas Papadimitriou
277 8d08f18a Kostas Papadimitriou
        case 'object':
278 8d08f18a Kostas Papadimitriou
279 8d08f18a Kostas Papadimitriou
// Due to a specification blunder in ECMAScript, typeof null is 'object',
280 8d08f18a Kostas Papadimitriou
// so watch out for that case.
281 8d08f18a Kostas Papadimitriou
282 8d08f18a Kostas Papadimitriou
            if (!value) {
283 8d08f18a Kostas Papadimitriou
                return 'null';
284 8d08f18a Kostas Papadimitriou
            }
285 8d08f18a Kostas Papadimitriou
286 8d08f18a Kostas Papadimitriou
// Make an array to hold the partial results of stringifying this object value.
287 8d08f18a Kostas Papadimitriou
288 8d08f18a Kostas Papadimitriou
            gap += indent;
289 8d08f18a Kostas Papadimitriou
            partial = [];
290 8d08f18a Kostas Papadimitriou
291 8d08f18a Kostas Papadimitriou
// Is the value an array?
292 8d08f18a Kostas Papadimitriou
293 8d08f18a Kostas Papadimitriou
            if (Object.prototype.toString.apply(value) === '[object Array]') {
294 8d08f18a Kostas Papadimitriou
295 8d08f18a Kostas Papadimitriou
// The value is an array. Stringify every element. Use null as a placeholder
296 8d08f18a Kostas Papadimitriou
// for non-JSON values.
297 8d08f18a Kostas Papadimitriou
298 8d08f18a Kostas Papadimitriou
                length = value.length;
299 8d08f18a Kostas Papadimitriou
                for (i = 0; i < length; i += 1) {
300 8d08f18a Kostas Papadimitriou
                    partial[i] = str(i, value) || 'null';
301 8d08f18a Kostas Papadimitriou
                }
302 8d08f18a Kostas Papadimitriou
303 8d08f18a Kostas Papadimitriou
// Join all of the elements together, separated with commas, and wrap them in
304 8d08f18a Kostas Papadimitriou
// brackets.
305 8d08f18a Kostas Papadimitriou
306 8d08f18a Kostas Papadimitriou
                v = partial.length === 0 ? '[]' : gap ?
307 8d08f18a Kostas Papadimitriou
                    '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
308 8d08f18a Kostas Papadimitriou
                    '[' + partial.join(',') + ']';
309 8d08f18a Kostas Papadimitriou
                gap = mind;
310 8d08f18a Kostas Papadimitriou
                return v;
311 8d08f18a Kostas Papadimitriou
            }
312 8d08f18a Kostas Papadimitriou
313 8d08f18a Kostas Papadimitriou
// If the replacer is an array, use it to select the members to be stringified.
314 8d08f18a Kostas Papadimitriou
315 8d08f18a Kostas Papadimitriou
            if (rep && typeof rep === 'object') {
316 8d08f18a Kostas Papadimitriou
                length = rep.length;
317 8d08f18a Kostas Papadimitriou
                for (i = 0; i < length; i += 1) {
318 8d08f18a Kostas Papadimitriou
                    if (typeof rep[i] === 'string') {
319 8d08f18a Kostas Papadimitriou
                        k = rep[i];
320 8d08f18a Kostas Papadimitriou
                        v = str(k, value);
321 8d08f18a Kostas Papadimitriou
                        if (v) {
322 8d08f18a Kostas Papadimitriou
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
323 8d08f18a Kostas Papadimitriou
                        }
324 8d08f18a Kostas Papadimitriou
                    }
325 8d08f18a Kostas Papadimitriou
                }
326 8d08f18a Kostas Papadimitriou
            } else {
327 8d08f18a Kostas Papadimitriou
328 8d08f18a Kostas Papadimitriou
// Otherwise, iterate through all of the keys in the object.
329 8d08f18a Kostas Papadimitriou
330 8d08f18a Kostas Papadimitriou
                for (k in value) {
331 8d08f18a Kostas Papadimitriou
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
332 8d08f18a Kostas Papadimitriou
                        v = str(k, value);
333 8d08f18a Kostas Papadimitriou
                        if (v) {
334 8d08f18a Kostas Papadimitriou
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
335 8d08f18a Kostas Papadimitriou
                        }
336 8d08f18a Kostas Papadimitriou
                    }
337 8d08f18a Kostas Papadimitriou
                }
338 8d08f18a Kostas Papadimitriou
            }
339 8d08f18a Kostas Papadimitriou
340 8d08f18a Kostas Papadimitriou
// Join all of the member texts together, separated with commas,
341 8d08f18a Kostas Papadimitriou
// and wrap them in braces.
342 8d08f18a Kostas Papadimitriou
343 8d08f18a Kostas Papadimitriou
            v = partial.length === 0 ? '{}' : gap ?
344 8d08f18a Kostas Papadimitriou
                '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
345 8d08f18a Kostas Papadimitriou
                '{' + partial.join(',') + '}';
346 8d08f18a Kostas Papadimitriou
            gap = mind;
347 8d08f18a Kostas Papadimitriou
            return v;
348 8d08f18a Kostas Papadimitriou
        }
349 8d08f18a Kostas Papadimitriou
    }
350 8d08f18a Kostas Papadimitriou
351 8d08f18a Kostas Papadimitriou
// If the JSON object does not yet have a stringify method, give it one.
352 8d08f18a Kostas Papadimitriou
353 8d08f18a Kostas Papadimitriou
    if (typeof JSON.stringify !== 'function') {
354 8d08f18a Kostas Papadimitriou
        JSON.stringify = function (value, replacer, space) {
355 8d08f18a Kostas Papadimitriou
356 8d08f18a Kostas Papadimitriou
// The stringify method takes a value and an optional replacer, and an optional
357 8d08f18a Kostas Papadimitriou
// space parameter, and returns a JSON text. The replacer can be a function
358 8d08f18a Kostas Papadimitriou
// that can replace values, or an array of strings that will select the keys.
359 8d08f18a Kostas Papadimitriou
// A default replacer method can be provided. Use of the space parameter can
360 8d08f18a Kostas Papadimitriou
// produce text that is more easily readable.
361 8d08f18a Kostas Papadimitriou
362 8d08f18a Kostas Papadimitriou
            var i;
363 8d08f18a Kostas Papadimitriou
            gap = '';
364 8d08f18a Kostas Papadimitriou
            indent = '';
365 8d08f18a Kostas Papadimitriou
366 8d08f18a Kostas Papadimitriou
// If the space parameter is a number, make an indent string containing that
367 8d08f18a Kostas Papadimitriou
// many spaces.
368 8d08f18a Kostas Papadimitriou
369 8d08f18a Kostas Papadimitriou
            if (typeof space === 'number') {
370 8d08f18a Kostas Papadimitriou
                for (i = 0; i < space; i += 1) {
371 8d08f18a Kostas Papadimitriou
                    indent += ' ';
372 8d08f18a Kostas Papadimitriou
                }
373 8d08f18a Kostas Papadimitriou
374 8d08f18a Kostas Papadimitriou
// If the space parameter is a string, it will be used as the indent string.
375 8d08f18a Kostas Papadimitriou
376 8d08f18a Kostas Papadimitriou
            } else if (typeof space === 'string') {
377 8d08f18a Kostas Papadimitriou
                indent = space;
378 8d08f18a Kostas Papadimitriou
            }
379 8d08f18a Kostas Papadimitriou
380 8d08f18a Kostas Papadimitriou
// If there is a replacer, it must be a function or an array.
381 8d08f18a Kostas Papadimitriou
// Otherwise, throw an error.
382 8d08f18a Kostas Papadimitriou
383 8d08f18a Kostas Papadimitriou
            rep = replacer;
384 8d08f18a Kostas Papadimitriou
            if (replacer && typeof replacer !== 'function' &&
385 8d08f18a Kostas Papadimitriou
                    (typeof replacer !== 'object' ||
386 8d08f18a Kostas Papadimitriou
                    typeof replacer.length !== 'number')) {
387 8d08f18a Kostas Papadimitriou
                throw new Error('JSON.stringify');
388 8d08f18a Kostas Papadimitriou
            }
389 8d08f18a Kostas Papadimitriou
390 8d08f18a Kostas Papadimitriou
// Make a fake root object containing our value under the key of ''.
391 8d08f18a Kostas Papadimitriou
// Return the result of stringifying the value.
392 8d08f18a Kostas Papadimitriou
393 8d08f18a Kostas Papadimitriou
            return str('', {'': value});
394 8d08f18a Kostas Papadimitriou
        };
395 8d08f18a Kostas Papadimitriou
    }
396 8d08f18a Kostas Papadimitriou
397 8d08f18a Kostas Papadimitriou
398 8d08f18a Kostas Papadimitriou
// If the JSON object does not yet have a parse method, give it one.
399 8d08f18a Kostas Papadimitriou
400 8d08f18a Kostas Papadimitriou
    if (typeof JSON.parse !== 'function') {
401 8d08f18a Kostas Papadimitriou
        JSON.parse = function (text, reviver) {
402 8d08f18a Kostas Papadimitriou
403 8d08f18a Kostas Papadimitriou
// The parse method takes a text and an optional reviver function, and returns
404 8d08f18a Kostas Papadimitriou
// a JavaScript value if the text is a valid JSON text.
405 8d08f18a Kostas Papadimitriou
406 8d08f18a Kostas Papadimitriou
            var j;
407 8d08f18a Kostas Papadimitriou
408 8d08f18a Kostas Papadimitriou
            function walk(holder, key) {
409 8d08f18a Kostas Papadimitriou
410 8d08f18a Kostas Papadimitriou
// The walk method is used to recursively walk the resulting structure so
411 8d08f18a Kostas Papadimitriou
// that modifications can be made.
412 8d08f18a Kostas Papadimitriou
413 8d08f18a Kostas Papadimitriou
                var k, v, value = holder[key];
414 8d08f18a Kostas Papadimitriou
                if (value && typeof value === 'object') {
415 8d08f18a Kostas Papadimitriou
                    for (k in value) {
416 8d08f18a Kostas Papadimitriou
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
417 8d08f18a Kostas Papadimitriou
                            v = walk(value, k);
418 8d08f18a Kostas Papadimitriou
                            if (v !== undefined) {
419 8d08f18a Kostas Papadimitriou
                                value[k] = v;
420 8d08f18a Kostas Papadimitriou
                            } else {
421 8d08f18a Kostas Papadimitriou
                                delete value[k];
422 8d08f18a Kostas Papadimitriou
                            }
423 8d08f18a Kostas Papadimitriou
                        }
424 8d08f18a Kostas Papadimitriou
                    }
425 8d08f18a Kostas Papadimitriou
                }
426 8d08f18a Kostas Papadimitriou
                return reviver.call(holder, key, value);
427 8d08f18a Kostas Papadimitriou
            }
428 8d08f18a Kostas Papadimitriou
429 8d08f18a Kostas Papadimitriou
430 8d08f18a Kostas Papadimitriou
// Parsing happens in four stages. In the first stage, we replace certain
431 8d08f18a Kostas Papadimitriou
// Unicode characters with escape sequences. JavaScript handles many characters
432 8d08f18a Kostas Papadimitriou
// incorrectly, either silently deleting them, or treating them as line endings.
433 8d08f18a Kostas Papadimitriou
434 8d08f18a Kostas Papadimitriou
            text = String(text);
435 8d08f18a Kostas Papadimitriou
            cx.lastIndex = 0;
436 8d08f18a Kostas Papadimitriou
            if (cx.test(text)) {
437 8d08f18a Kostas Papadimitriou
                text = text.replace(cx, function (a) {
438 8d08f18a Kostas Papadimitriou
                    return '\\u' +
439 8d08f18a Kostas Papadimitriou
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
440 8d08f18a Kostas Papadimitriou
                });
441 8d08f18a Kostas Papadimitriou
            }
442 8d08f18a Kostas Papadimitriou
443 8d08f18a Kostas Papadimitriou
// In the second stage, we run the text against regular expressions that look
444 8d08f18a Kostas Papadimitriou
// for non-JSON patterns. We are especially concerned with '()' and 'new'
445 8d08f18a Kostas Papadimitriou
// because they can cause invocation, and '=' because it can cause mutation.
446 8d08f18a Kostas Papadimitriou
// But just to be safe, we want to reject all unexpected forms.
447 8d08f18a Kostas Papadimitriou
448 8d08f18a Kostas Papadimitriou
// We split the second stage into 4 regexp operations in order to work around
449 8d08f18a Kostas Papadimitriou
// crippling inefficiencies in IE's and Safari's regexp engines. First we
450 8d08f18a Kostas Papadimitriou
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
451 8d08f18a Kostas Papadimitriou
// replace all simple value tokens with ']' characters. Third, we delete all
452 8d08f18a Kostas Papadimitriou
// open brackets that follow a colon or comma or that begin the text. Finally,
453 8d08f18a Kostas Papadimitriou
// we look to see that the remaining characters are only whitespace or ']' or
454 8d08f18a Kostas Papadimitriou
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
455 8d08f18a Kostas Papadimitriou
456 8d08f18a Kostas Papadimitriou
            if (/^[\],:{}\s]*$/
457 8d08f18a Kostas Papadimitriou
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
458 8d08f18a Kostas Papadimitriou
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
459 8d08f18a Kostas Papadimitriou
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
460 8d08f18a Kostas Papadimitriou
461 8d08f18a Kostas Papadimitriou
// In the third stage we use the eval function to compile the text into a
462 8d08f18a Kostas Papadimitriou
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
463 8d08f18a Kostas Papadimitriou
// in JavaScript: it can begin a block or an object literal. We wrap the text
464 8d08f18a Kostas Papadimitriou
// in parens to eliminate the ambiguity.
465 8d08f18a Kostas Papadimitriou
466 8d08f18a Kostas Papadimitriou
                j = eval('(' + text + ')');
467 8d08f18a Kostas Papadimitriou
468 8d08f18a Kostas Papadimitriou
// In the optional fourth stage, we recursively walk the new structure, passing
469 8d08f18a Kostas Papadimitriou
// each name/value pair to a reviver function for possible transformation.
470 8d08f18a Kostas Papadimitriou
471 8d08f18a Kostas Papadimitriou
                return typeof reviver === 'function' ?
472 8d08f18a Kostas Papadimitriou
                    walk({'': j}, '') : j;
473 8d08f18a Kostas Papadimitriou
            }
474 8d08f18a Kostas Papadimitriou
475 8d08f18a Kostas Papadimitriou
// If the text is not JSON parseable, then a SyntaxError is thrown.
476 8d08f18a Kostas Papadimitriou
477 8d08f18a Kostas Papadimitriou
            throw new SyntaxError('JSON.parse');
478 8d08f18a Kostas Papadimitriou
        };
479 8d08f18a Kostas Papadimitriou
    }
480 8d08f18a Kostas Papadimitriou
}());