
JSON = new function(){

	this.decode = function(){

		var	filter, result, self, tmp;

		if($$("toString")) {

			switch(arguments.length){

				case	2:

					self = arguments[0];

					filter = arguments[1];

					break;

				case	1:

					if($[typeof arguments[0]](arguments[0]) === Function) {

						self = this;

						filter = arguments[0];

					}

					else

						self = arguments[0];

					break;

				default:

					self = this;

					break;

			};

			if(rc.test(self)){

				try{

					result = e("(".concat(self, ")"));

					if(filter && result !== null && (tmp = $[typeof result](result)) && (tmp === Array || tmp === Object)){

						for(self in result)

							result[self] = v(self, result) ? filter(self, result[self]) : result[self];

					}

				}

				catch(z){}

			}

			else {

				throw new JSONError("bad data");

			}

		};

		return result;

	};

	this.encode = function(){

		var	self = arguments.length ? arguments[0] : this,

			result, tmp;

		if(self === null)

			result = "null";

		else if(self !== undefined && (tmp = $[typeof self](self))) {

			switch(tmp){

				case	Array:

					result = [];

					for(var	i = 0, j = 0, k = self.length; j < k; j++) {

						if(self[j] !== undefined && (tmp = JSON.encode(self[j])))

							result[i++] = tmp;

					};

					result = "[".concat(result.join(","), "]");

					break;

				case	Boolean:

					result = String(self);

					break;

				case	Date:

					result = '"'.concat(self.getFullYear(), '-', d(self.getMonth() + 1), '-', d(self.getDate()), 'T', d(self.getHours()), ':', d(self.getMinutes()), ':', d(self.getSeconds()), '"');

					break;

				case	Function:

					break;

				case	Number:

					result = isFinite(self) ? String(self) : "null";

					break;

				case	String:

					result = '"'.concat(self.replace(rs, s).replace(ru, u), '"');

					break;

				default:

					var	i = 0, key;

					result = [];

					for(key in self) {

						if(self[key] !== undefined && (tmp = JSON.encode(self[key])))

							result[i++] = '"'.concat(key.replace(rs, s).replace(ru, u), '":', tmp);

					};

					result = "{".concat(result.join(","), "}");

					break;

			}

		};

		return result;

	};

	

	this.toDate = function(){

		var	self = arguments.length ? arguments[0] : this,

			result;

		if(rd.test(self)){

			result = new Date;

			result.setHours(i(self, 11, 2));

			result.setMinutes(i(self, 14, 2));

			result.setSeconds(i(self, 17, 2));

			result.setMonth(i(self, 5, 2) - 1);

			result.setDate(i(self, 8, 2));

			result.setFullYear(i(self, 0, 4));

		}

		else if(rt.test(self))

			result = new Date(self * 1000);

		return result;

	};

	var	c = {"\b":"b","\t":"t","\n":"n","\f":"f","\r":"r",'"':'"',"\\":"\\","/":"/"},

		d = function(n){return n<10?"0".concat(n):n},

		e = function(c,f,e){e=eval;delete eval;if(typeof eval==="undefined")eval=e;f=eval(""+c);eval=e;return f},

		i = function(e,p,l){return 1*e.substr(p,l)},

		p = ["","000","00","0",""],

		rc = null,

		rd = /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/,

		rs = /(\x5c|\x2F|\x22|[\x0c-\x0d]|[\x08-\x0a])/g,

		rt = /^([0-9]+|[0-9]+[,\.][0-9]{1,3})$/,

		ru = /([\x00-\x07]|\x0b|[\x0e-\x1f])/g,

		s = function(i,d){return "\\".concat(c[d])},

		u = function(i,d){

			var	n=d.charCodeAt(0).toString(16);

			return "\\u".concat(p[n.length],n)

		},

		v = function(k,v){return $[typeof result](result)!==Function&&(v.hasOwnProperty?v.hasOwnProperty(k):v.constructor.prototype[k]!==v[k])},

		$ = {

			"boolean":function(){return Boolean},

			"function":function(){return Function},

			"number":function(){return Number},

			"object":function(o){return o instanceof o.constructor?o.constructor:null},

			"string":function(){return String},

			"undefined":function(){return null}

		},

		$$ = function(m){

			function $(c,t){t=c[m];delete c[m];try{e(c)}catch(z){c[m]=t;return 1}};

			return $(Array)&&$(Object)

		};

	try{rc=new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}

	catch(z){rc=/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/}

};