
if (DHL == undefined) var DHL = {};
if (DHL.FORMAT == undefined) DHL.FORMAT = {};

(DHL.FORMAT.JSON = function () {

	// Format integers to have at least two digits.
	function f(n) {    
	    return n < 10 ? '0' + n : n;
	}
	
	Date.prototype.toJSON = function () {

	return this.getUTCFullYear()   + '-' +
		f(this.getUTCMonth() + 1) + '-' +
		f(this.getUTCDate())      + 'T' +
		f(this.getUTCHours())     + ':' +
		f(this.getUTCMinutes())   + ':' +
		f(this.getUTCSeconds())   + 'Z';
	};


	var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
	    gap,
	    indent,
	    meta = {    // table of character substitutions
	        '\b': '\\b', '\t': '\\t', '\n': '\\n',
	        '\f': '\\f', '\r': '\\r', '"' : '\\"',
	        '\\': '\\\\'
	    },
   	 rep
	;

	function quote(string) {

		return escapeable.test(string) ?
			'"' + string.replace(escapeable, function (a) {
			    var c = meta[a];
			    if (typeof c === 'string') {
			        return c;
			    }
			    c = a.charCodeAt();
			    return '\\u00' + Math.floor(c / 16).toString(16) +
			                               (c % 16).toString(16);
			}) + '"' :
			'"' + string + '"';
	}

	function str(key, holder) {
		var i,          // The loop counter.
		    k,          // The member key.
		    v,          // The member value.
		    length,
		    mind = gap,
		    partial,
		    value = holder[key];


		if (value && typeof value === 'object' &&
		        typeof value.toJSON === 'function') {
		    value = value.toJSON(key);
		}

		if (typeof rep === 'function') {
		    value = rep.call(holder, key, value);
		}

		switch (typeof value) {
		case 'string':
		    return quote(value);
		case 'number':
		return isFinite(value) ? String(value) : 'null';
		case 'boolean':
		case 'null':
			return String(value);
		case 'object':
			if (!value) {
			    return 'null';
			}

			gap += indent;
			partial = [];
	
			if (typeof value.length === 'number' &&
				!(value.propertyIsEnumerable('length'))
			) {

				length = value.length;
				for (i = 0; i < length; i += 1) {
				    partial[i] = str(i, value) || 'null';
				}

			    v = partial.length === 0 ? '[]' :
			        gap ? '[\n' + gap + partial.join(',\n' + gap) +
			                  '\n' + mind + ']' :
			              '[' + partial.join(',') + ']';
			    gap = mind;
			    return v;
			}
			
			if (typeof rep === 'object') {
			    length = rep.length;
			    for (i = 0; i < length; i += 1) {
			        k = rep[i];
			        if (typeof k === 'string') {
			            v = str(k, value, rep);
			            if (v) {
			                partial.push(quote(k) + (gap ? ': ' : ':') + v);
			            }
			        }
			    }
			} else {
				for (k in value) {
				    v = str(k, value, rep);
				    if (v) {
				        partial.push(quote(k) + (gap ? ': ' : ':') + v);
				    }
				}
			}

			v = partial.length === 0 ? '{}' :
			    gap ? '{\n' + gap + partial.join(',\n' + gap) +
			              '\n' + mind + '}' :
			          '{' + partial.join(',') + '}';
			gap = mind;
			return v;
	    }
	}

	return {
		stringify: function (value, replacer, space) {

		var i;
		gap = '';
		indent = '';
		if (space) {

			if (typeof space === 'number') {
			   for (i = 0; i < space; i += 1) {
			   	indent += ' ';
				}
		   } else if (typeof space === 'string') {
		       indent = space;
		   }
		}

		if (!replacer) {
		    rep = function (key, value) {
		        if (!Object.hasOwnProperty.call(this, key)) {
		            return undefined;
		        }
		        return value;
		    };
		} else if (typeof replacer === 'function' ||
		        (typeof replacer === 'object' &&
		         typeof replacer.length === 'number')) {
					rep = replacer;
		} else {
		    throw new Error('JSON.stringify');
		}

	   	return str('', {'': value});
		},


      parse: function (text, reviver) {
		
		var j;

			function walk(holder, key) {
			    var k, v, value = holder[key];
			    if (value && typeof value === 'object') {
			        for (k in value) {
			            if (Object.hasOwnProperty.call(value, k)) {
			                v = walk(value, k);
			                if (v !== undefined) {
			                    value[k] = v;
			                } else {
			                    delete value[k];
			                }
			            }
			        }
			    }
			    return reviver.call(holder, key, value);
			}

			if (
				/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
				replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
				replace(/(?:^|:|,)(?:\s*\[)+/g, ''))
			) {

				j = eval('(' + text + ')');

				return typeof reviver === 'function' ? walk({'': j}, '') : j;
			}

		   throw new SyntaxError('JSON.parse');
		},
		quote: quote
	};
	
	if (DHL.FORMAT.JSON.className == undefined) {
		DHL.FORMAT.JSON.className = 'DHL.FORMAT.JSON';
	}	
})();
