/**
 * @class Ext.JSON
 * Modified version of Douglas Crockford"s json.js that doesn"t
 * mess with the Object prototype
 * http://www.json.org/js.html
 * @singleton
 */

Ext.JSON = new(function() {
   
var useHasOwn = !! {}.hasOwnProperty,
    isNative
= function() {
       
var useNative = null;

       
return function() {
           
if (useNative === null) {
                useNative
= Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
           
}

           
return useNative;
       
};
   
}(),
    pad
= function(n) {
       
return n < 10 ? "0" + n : n;
   
},
    doDecode
= function(json) {
       
return eval("(" + json + ')');
   
},
    doEncode
= function(o) {
       
if (!Ext.isDefined(o) || o === null) {
           
return "null";
       
} else if (Ext.isArray(o)) {
           
return encodeArray(o);
       
} else if (Ext.isDate(o)) {
           
return Ext.JSON.encodeDate(o);
       
} else if (Ext.isString(o)) {
           
return encodeString(o);
       
} else if (typeof o == "number") {
           
//don't use isNumber here, since finite checks happen inside isNumber
           
return isFinite(o) ? String(o) : "null";
       
} else if (Ext.isBoolean(o)) {
           
return String(o);
       
} else if (Ext.isObject(o)) {
           
return encodeObject(o);
       
} else if (typeof o === "function") {
           
return "null";
       
}
       
return 'undefined';
   
},
    m
= {
       
"\b": '\\b',
       
"\t": '\\t',
       
"\n": '\\n',
       
"\f": '\\f',
       
"\r": '\\r',
       
'"': '\\"',
       
"\\": '\\\\',
       
'\x0b': '\\u000b' //ie doesn't handle \v
   
},
    charToReplace
= /[\\\"\x00-\x1f\x7f-\uffff]/g,
    encodeString
= function(s) {
       
return '"' + s.replace(charToReplace, function(a) {
           
var c = m[a];
           
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
       
}) + '"';
   
},
    encodeArray
= function(o) {
       
var a = ["[", ""],
       
// Note empty string in case there are no serializable members.
        len
= o.length,
        i
;
       
for (i = 0; i < len; i += 1) {
            a
.push(doEncode(o[i]), ',');
       
}
       
// Overwrite trailing comma (or empty string)
        a
[a.length - 1] = ']';
       
return a.join("");
   
},
    encodeObject
= function(o) {
       
var a = ["{", ""],
       
// Note empty string in case there are no serializable members.
        i
;
       
for (i in o) {
           
if (!useHasOwn || o.hasOwnProperty(i)) {
                a
.push(doEncode(i), ":", doEncode(o[i]), ',');
           
}
       
}
       
// Overwrite trailing comma (or empty string)
        a
[a.length - 1] = '}';
       
return a.join("");
   
};

    /**
     * <p>Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression.
     * <b>The returned value includes enclosing double quotation marks.</b></p>
     * <p>The default return format is "yyyy-mm-ddThh:mm:ss".</p>
     * <p>To override this:</p><pre><code>
     Ext.JSON.encodeDate = function(d) {
     return d.format('"Y-m-d"');
     };
     </code></pre>
     * @param {Date} d The Date to encode
     * @return {String} The string literal to use in a JSON string.
     */

   
this.encodeDate = function(o) {
       
return '"' + o.getFullYear() + "-"
       
+ pad(o.getMonth() + 1) + "-"
       
+ pad(o.getDate()) + "T"
       
+ pad(o.getHours()) + ":"
       
+ pad(o.getMinutes()) + ":"
       
+ pad(o.getSeconds()) + '"';
   
};

    /**
     * Encodes an Object, Array or other value
     * @param {Mixed} o The variable to encode
     * @return {String} The JSON string
     */

   
this.encode = function() {
       
var ec;
       
return function(o) {
           
if (!ec) {
               
// setup encoding function on first access
                ec
= isNative() ? JSON.stringify : doEncode;
           
}
           
return ec(o);
       
};
   
}();


    /**
     * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError unless the safe option is set.
     * @param {String} json The JSON string
     * @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid.
     * @return {Object} The resulting object
     */

   
this.decode = function() {
       
var dc;
       
return function(json, safe) {
           
if (!dc) {
               
// setup decoding function on first access
                dc
= isNative() ? JSON.parse : doDecode;
           
}
           
try {
               
return dc(json);
           
} catch (e) {
               
if (safe === true) {
                   
return null;
               
}
               
Ext.Error.raise({
                    sourceClass
: "Ext.JSON",
                    sourceMethod
: "decode",
                    msg
: "You're trying to decode and invalid JSON String: " + json
               
});
           
}
       
};
   
}();

})();
/**
 * Shorthand for {@link Ext.JSON#encode}
 * @param {Mixed} o The variable to encode
 * @return {String} The JSON string
 * @member Ext
 * @method encode
 */

Ext.encode = Ext.JSON.encode;
/**
 * Shorthand for {@link Ext.JSON#decode}
 * @param {String} json The JSON string
 * @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid.
 * @return {Object} The resulting object
 * @member Ext
 * @method decode
 */

Ext.decode = Ext.JSON.decode;