//
// Copyright(C) 2007, Simon Howard
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Convert arbitrary Javascript data to JSON.
//

var JSONGen = {

	stringToJSON: function(string) {

		var mapping = {
			"\b": "\\b",
			"\t": "\\t",
			"\n": "\\n",
			"\f": "\\f",
			"\r": "\\r",
			"\"": "\\\"",
			"\\": "\\\\"
		}

		var escaped = string.replace(/./g, function(a, b) {
			var mapped = mapping[a]

			if (mapped) {
				return mapped
			} else {
				return a
			}
		})

		return "\"" + escaped + "\""
	},

	arrayToJSON: function(array) {
		var stringValues = []

		for (var i=0; i<array.length; ++i) {
			stringValues.push(JSONGen.toJSON(array[i]))
		}

		return "[" + stringValues.join(", ") + "]"
	},

	mappingToJSON: function(key, value) {
		var result = (
			JSONGen.toJSON(key) +
			":" +
			JSONGen.toJSON(value)
		)

		return result
	},

	hashToJSON: function(object) {
		var mappings = []

		for (var key in object) {
			var value = object[key]

			mappings.push(JSONGen.mappingToJSON(key, value))
		}

		return "{" + mappings.join(", ") + "}"
	},

	objectToJSON: function(object) {
		if (object == null) {
			return "null"
		} else if (object instanceof Array) {
			return JSONGen.arrayToJSON(object)
		} else if (object instanceof Number) {
			return object.toString()
		} else if (object.toJSON) {
			return object.toJSON()
		} else {
			return JSONGen.hashToJSON(object)
		}
	},

	booleanToJSON: function(expression) {
		if (expression == true) {
			return "true"
		} else {
			return "false"
		}
	},

	toJSON: function(expression) {

		var exprType = typeof(expression)

		if (exprType == "string") {
			return JSONGen.stringToJSON(expression)
		} else if (exprType == "object") {
			return JSONGen.objectToJSON(expression)
		} else if (exprType == "number") {
			return new Number(expression).toString()
		} else if (exprType == "boolean") {
			return JSONGen.booleanToJSON(expression)
		} else {
			throw("Expression type cannot be converted to JSON: "
			      + exprType)
		}
	},

	parseJSON: function(json_text) {
		return eval("(" + json_text + ")")
	}
}



