// VC-JSON
/*

PROJECT:	JDM (Java Dynamic Machine)
PROGRAMMER:	G. Patnude
FILE:		vc-json/vc-json.js
PURPOSE:	GO! SERIALIZER & DE-SERIALIZER...

Includes functions for:

	-- JSON/GO! Serialization
	-- JSON/GO! DE-Serialization
	-- JSON/GO! Parsing

*/

var JSON = {
	
	
	version : "0.000a",
	org: 'http://www.JSON.org',
	copyright: '(c)2005 JSON.org',
	license: 'http://www.crockford.com/JSON/license.html',    
	stringify: function stringify(arg) {
		
	var c, i, l, s = '', v;
	switch (typeof arg) {
		
		case 'object':
		
			if (arg) {
			    
				if (arg.constructor == Array) {
					
					for (i = 0; i < arg.length; ++i) {
						
						v = stringify(arg[i]);
						if (s) {s += ',';}
						s += v;
					}
					
					return '[' + s + ']';
					
				} else if (typeof arg.toString != 'undefined') {
					
					for (i in arg) {
						
						v = stringify(arg[i]);
						if (typeof v != 'function') {
							
							if (s) {s += ',';}
							s += stringify(i) + ':' + v;
						}
					}
				
					return '{' + s + '}';
				}
			}
			
			return 'null';
		    
		case 'number': 
		
			return isFinite(arg) ? String(arg) : 'null';
			
		case 'string':
		
			l = arg.length;
			s = '"';
			for (i = 0; i < l; i += 1) {
		
				c = arg.charAt(i);
				if (c >= ' ') {
		
					if (c == '\\' || c == '"') {s += '\\';}
					s += c;
					
				} else {
					
				    switch (c) {
			
					case '\b':
					
						s += '\\b';
						break;

					case '\f':
					
						s += '\\f';
						break;
						
					case '\n':
					
						s += '\\n';
						break;
						
					case '\r':
					
						s += '\\r';
						break;
						
					case '\t':
					
						s += '\\t';
						break;
						
					default:
					
						c = c.charCodeAt();
						s += '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
						break;
						
				    }
			}
		    }
		    
		    return s + '"';
		
		case 'boolean':
		
			return String(arg);
			
		case 'null':
		
			return 'null';
			
		default:
		
		    return 'null';
	}
	
},

getType: function getType(t) {
	
	// UTIL.trace("getType:" + t.constructor.toString().split(" ")[1]);
	return t.constructor.toString().split(" ")[1];

},

gparse: function gparse(str) {	
	
	if ((str != 'undefined') && (str != null)) { 
	
		// str = str.replace(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{6}/gi, "[" + RegExp.lastMatch +"]");
		try {
			
			// var X = eval(str);
			var X = new Object(str);
			if (this.getType(X) == 'String()') {
				
				X = eval(X);			
				for (var t in X) {
					
					var type = this.getType(X[t]);
					// UTIL.trace(t + " TYPE is -> " + type);
					if ((type == 'Object()') || (type == 'Array()')) {
						
						this.gparse(X[t]);
						
					} else {
				
						// UTIL.trace(t + "[" + X[t].toString() + "] is a " + this.getType(X[t]));
						
					}
					
				}
			
			} else {
				
				// UTIL.trace("X is apparently not an object...");
				
			}
			
		} catch (e) {
			
			// UTIL.trace("Eval of (X) failed...");
			
		}
	
		
		
	}
	
	return;
	
},

parse: function parse(text) {
	
	var at = 0;
	var ch = ' ';
	var val;	
	var r = this.gparse(text);
	
        function error(msg, m) {
		
		// throw {name: 'JSONError', message: m, at: at - 1, text: "'" + text + "'"};
		// throw {name: 'JSONError', message: m, at: at - 1};
		// alert("something bad happened..." + m);
		UTIL.trace("JSO::error(): CALLER:" + error.caller + "MSG:" + msg + ":" + m);
		return;
		
        }

	function next() {
	
		ch = text.charAt(at);
		at += 1;
		return ch;
	
	}

        function white() {
		
		while (ch) {
		    
			if (ch <= ' ') {
				
				next();
				
			} else if (ch == '/') {
				
				switch (next()) {
	
					case '/':
					
						while (next() && ch != '\n' && ch != '\r') {}
						break;
						
					case '*':
					
						next();
						for (;;) {
							
							if (ch) {
			
								if (ch == '*') {
		
									if (next() == '/') {
		
										next();
										break;
										
									}
								
								} else {
					
									next();
								}
								
							} else {
					
								error("Unterminated comment");
							}
						}
						
						break;
	
					default:
					
						error("white() Syntax error somewhere:" + ch);
				}
	
			} else {
				
				break;
			}
		}
	}

        function string() {

		var i, s = '', t, u;
		if (ch == '"') {
			
outer:			while (next()) {
	
				if (ch == '"') {
					
					next();
					return s;
					
				} else if (ch == '\\') {

					switch (next()) {
				
						case 'null':
			
							s  += null;
							break;
				
						case 'b':
			
							s += '\b';
							break;

						case 'f':

							s += '\f';
							break;
							
						case 'n':
		
							s += '\n';
							break;
							
						case 'r':

							s += '\r';
							break;
							
						case 't':

							s += '\t';
							break;
							
						case 'u':
						
							u = 0;
							for (i = 0; i < 4; i += 1) {
								
								t = parseInt(next(), 16);
								if (!isFinite(t)) {
									
									break outer;
								}
								
								u = u * 16 + t;
							}
							
							s += String.fromCharCode(u);
							break;
							
						default:
				
							s += ch;
							break;
					}
					
				} else {
			
					s += ch;
		    		}
				
			}

		}
		
		error("Bad string");

	}

	function array() {
		
		var a = [];		
		if (ch == '[') {
			    
			next();
			white();
			if (ch == ']') {

				next();
				return a;
			}
		
			while (ch) {

				a.push(value());
				white();
				if (ch == ']') {

					next();
					return a;

				} else if (ch != ',') {

					break;
				}
				
				next();
				white();
			}
		}
			
		error("Bad array");
		
	}

	function object() {
		
		var k, o = {};		
		if (ch == '{') {

			next();
			white();
			if (ch == '}') {

				next();
				return o;
			}
			
			while (ch) {

				k = string();
				white();
				if (ch != ':') {

					break;

				}
				
				next();
				o[k] = value();
				white();			
				if (ch == '}') {
			
					next();
					return o;
					
				} else if (ch != ',') {
	
					break;
				}
			
				next();
				white();
			}
		}
			
		error("Bad object");

	}

	function number() {
		
		var n = '', v;		
  		if (ch == '-') {
	
			n = '-';
			next();
			
		}
	
		while (ch >= '0' && ch <= '9') {
			
			n += ch;
			next();
		}
	
		if (ch == '.') {
	
			n += ch;
			while (next() && ch >= '0' && ch <= '9') {
	
				n += ch;
			}
			
		}		
		
		v = +n;				
		if (!isFinite(v)) {
			
			error("Bad number");
			
		} else {
			
			return v;
		}
	}

	function word() {

		try {
			
			switch (ch) {
			
				case 't':
				
					if (next() == 'r' && next() == 'u' && next() == 'e') {
	
						next();
						return true;
					}
					
					break;
					
				case 'f':
				
					if (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') {
	
						next();
						return false;
					}
	
					break;
					
				case 'n':
				
					if (next() == 'u' && next() == 'l' && next() == 'l') {
	
						next();
						return null;
					}
					
					break;
					
				default:
	
					break;
			}
			
		} catch (e) {

			error("Syntax error in word() " + ch, e);
			
		}
		
	}
	
	function value() {
		
		white();
		switch (ch) {

			case '{':

				return object();
	
			case '[':

				return array();
				
			case '"':

				return string();

			case '-':

				return number();
				
			case 'null':
			
				return null;				

			default:				
			
				val = (ch >= '0' && ch <= '9') ? number() : word();
				return val;
				// return (ch >= '0' && ch <= '9') ? number() : word();
				
		}
	}
	
	function isDate(d) {
		
		UTIL.trace("TESTING FOR A DATE:" + d);		
		var TYPES = [
			     
			["DATE", new RegExp(/(\d{4}-d{2}-d{2})/gi)], 
			["TIME", new RegExp(/(\d{2}:\d{2}:)/gi)],
			["TIMESTAMP", new RegExp(/(\d{4}-d{2}-d{2})\W+(\d{2}:\d{2}:\d{2})\.\d{6}/gi)]
			     
		];
		for  (m in TYPES) {
			
			UTIL.trace("TESTING FOR DATE:" + m);
			var type = m.test(d);
			
		}
		
		return type;
		
	}	
	
	return value();
	
	}

};

function isAlien(a) {

	return isObject(a) && typeof a.constructor != 'function';
	
}

function isArray(a) {

	return isObject(a) && a.constructor == Array;
	
}

function isBoolean(a) {

	return typeof a == 'boolean';
	
}

function isEmpty(o) {

	var i, v;
	if (isObject(o)) {
	
		for (i in o) {
		
			v = o[i];
			
			if (isUndefined(v) && isFunction(v)) {
			
				return false;
				
			}
			
		}
		
	}
	
	return true;
	
}

function isFunction(a) {

	return typeof a == 'function';
	
}

function isNull(a) {

	return typeof a == 'object' && !a;

}

function isNumber(a) {

	return typeof a == 'number' && isFinite(a);

}

function isObject(a) {

	return (a && typeof a == 'object') || isFunction(a);
	
}

function isString(a) {

	return typeof a == 'string';

}

function isUndefined(a) {

	return typeof a == 'undefined';

} 

function isIdentical(a, b) {

	return (a == b) ? true : false;

}

