$.extend(Object, {
	inspect : function(object) {
		try {
			if (Object.isUndefined(object))
				return 'undefined';
			if (object === null)
				return 'null';
			return object.inspect ? object.inspect() : object.toString();
		} catch (e) {
			if (e instanceof RangeError)
				return '...';
			throw e;
		}
	},

	toJSON : function(object) {
		var type = typeof object;
		switch (type) {
		case 'undefined':
		case 'function':
		case 'unknown':
			return;
		case 'boolean':
			return object.toString();
		}

		if (object === null)
			return 'null';
		if (object.toJSON)
			return object.toJSON();
		if (Object.isElement(object))
			return;

		var results = [];
		for ( var property in object) {
			var value = Object.toJSON(object[property]);
			// log(typeof(property));
	if (!Object.isUndefined(value))
		results.push(property.toJSON() + ': ' + value);
}

return '{' + results.join(', ') + '}';
},

toQueryString : function(object) {
return $H(object).toQueryString();
},

toHTML : function(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
},

keys : function(object) {
var keys = [];
for ( var property in object)
	keys.push(property);
return keys;
},

values : function(object) {
var values = [];
for ( var property in object)
	values.push(object[property]);
return values;
},

clone : function(object) {
return $.extend( {}, object);
},

isElement : function(object) {
return object && object.nodeType == 1;
},

isArray : function(object) {
return object && object.constructor === Array;
},

isHash : function(object) {
return object instanceof Hash;
},

isFunction : function(object) {
return typeof object == "function";
},

isString : function(object) {
return typeof object == "string";
},

isNumber : function(object) {
return typeof object == "number";
},

isUndefined : function(object) {
return typeof object == "undefined";
}
});

$.extend(Number.prototype, {
	toJSON : function() {
		return isFinite(this) ? this.toString() : 'null';
	}
});

$.extend(Array.prototype, {
	toJSON : function() {
		var results = [];
		
		for(var i=0; i<this.length; i++) {
			var object=this[i];
			var value = Object.toJSON(object);
			if (!Object.isUndefined(value))
				results.push(value);
		}
		return '[' + results.join(', ') + ']';
	}
});

$.extend(String.prototype, {
	gsub : function(pattern, replacement) {
		var result = '', source = this, match;
		replacement = arguments.callee.prepareReplacement(replacement);

		while (source.length > 0) {
			if (match = source.match(pattern)) {
				result += source.slice(0, match.index);
				result += String.interpret(replacement(match));
				source = source.slice(match.index + match[0].length);
			} else {
				result += source, source = '';
			}
		}
		return result;
	},

	inspect : function(useDoubleQuotes) {
		var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
			var character = String.specialChar[match[0]];
			return character ? character : '\\u00' + match[0].charCodeAt()
					.toPaddedString(2, 16);
		});
		if (useDoubleQuotes)
			return '"' + escapedString.replace(/"/g, '\\"') + '"';
		return "'" + escapedString.replace(/'/g, '\\\'') + "'";
	},

	toJSON : function() {
		return this.inspect(true);
	}
});

String.prototype.gsub.prepareReplacement = function(replacement) {
	if (Object.isFunction(replacement))
		return replacement;
	var template = new Template(replacement);
	return function(match) {
		return template.evaluate(match)
	};
};
