

com_adrianguenter = {};
com_adrianguenter.util = {};

String.prototype.multireplace = function(oldStringArray,newString,flags) {
	
	if( !isArray(oldStringArray) ) throw new Error('Unexpected type for arg oldStringArray');
	if( !isString(newString) ) throw new Error('Unexpected type for arg newString');
	if( !isString(flags) ) var flags = '';
	
	var thisString = this.toString();
	
	for( var i=0; i < oldStringArray.length; ++i )
		thisString = thisString.replace(oldStringArray[i], newString, flags);
	
	return thisString;
};

Array.prototype.inArray = function(obj) {
	return this.indexOf(obj) !== -1;
};

com_adrianguenter.util.ctrlChar = {
	
	/*  															*/
	/*  		ASCII CONTROL CHARACTERS							*/
	/*  															*/
	NUL	: unescape("%00"),	/* Null byte 							*/
	SOH	: unescape("%01"),	/* Start of heading 					*/
	STX	: unescape("%02"),	/* Start of text 						*/
	ETX	: unescape("%03"),	/* End of text 							*/
	EOT	: unescape("%04"),	/* End of transmission 					*/
	ENQ	: unescape("%05"),	/* Enquiry 								*/
	ACK	: unescape("%06"),	/* Acknowledge 							*/
	BEL	: unescape("%07"),	/* Ring terminal bell 					*/
	BS	: unescape("%08"),	/* Backspace 							*/
	HT	: unescape("%09"),	/* Horizontal tab 						*/
	LF	: unescape("%0A"),	/* Line feed 							*/
	VT	: unescape("%0B"),	/* Vertical tab 						*/
	FF	: unescape("%0C"),	/* Form feed 							*/
	CR	: unescape("%0D"),	/* Carriage return 						*/
	SO	: unescape("%0E"),	/* Shift out 							*/
	SI	: unescape("%0F"),	/* Shift in 							*/
	DLE	: unescape("%10"),	/* Data link escape 					*/
	DC1	: unescape("%11"),	/* Device control 1 					*/
	DC2	: unescape("%12"),	/* Device control 2 					*/
	DC3	: unescape("%13"),	/* Device control 3 					*/
	DC4	: unescape("%14"),	/* Device control 4 					*/
	NAK	: unescape("%15"),	/* Negative acknowledge 				*/
	SYN	: unescape("%16"),	/* Synchronous idle 					*/
	ETB	: unescape("%17"),	/* End of transmission block 			*/
	CAN	: unescape("%18"),	/* Cancel 								*/
	EM	: unescape("%19"),	/* End of medium 						*/
	SUB	: unescape("%1A"),	/* Substitute character 				*/
	ESC	: unescape("%1B"),	/* Escape 								*/
	FS	: unescape("%1C"),	/* File separator, Info separator 4 	*/
	GS	: unescape("%1D"),	/* Group separator, Info separator 3 	*/
	RS	: unescape("%1E"),	/* Record separator, Info separator 2	*/
	US	: unescape("%1F"),	/* Unit separator, Info separator 1		*/
	DEL	: unescape("%7F")	/* Delete 								*/
	/*  															*/
};

com_adrianguenter.util.isDefined = function(mixedVar) {
	
	if( typeof(mixedVar) !== 'undefined' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isObject = function(obj) {
	
	if( typeof(obj) === 'object' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isBool = function(val) {
	
	if( typeof(val) === 'boolean' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isString = function(val) {
	
	if( typeof(val) === 'string' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isNumber = function(val) {
	
	if( typeof(val) === 'number' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isJSON = function(val) {
	
	if( typeof(val) === 'string' && !(/^\s*$/.test(val)) )
	{
		val = val.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
		
		if(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(val))
			return true;
		else
			return false;
	} 
	else
		return false;
};

com_adrianguenter.util.isGenObject = function(obj) {
	
	if( typeof(obj) === 'object' && obj !== null && obj.constructor.toString().toLowerCase().indexOf('object') !== -1 )
		return true;
	else
		return false;
};

com_adrianguenter.util.isArray = function(obj) {
	
	if( typeof(obj) === 'object' && obj !== null && obj.constructor.toString().toLowerCase().indexOf('array') !== -1 )
		return true;
	else
		return false;
};

com_adrianguenter.util.isRegExp = function(obj) {
	
	if( typeof(obj) === 'object' && obj !== null && obj.constructor.toString().toLowerCase().indexOf('regexp') !== -1 )
		return true;
	else
		return false;
};

com_adrianguenter.util.isFunction = function(obj) {
	
	if( typeof(obj) === 'function' )
		return true;
	else
		return false;
};

com_adrianguenter.util.isDOMNode = function(obj) {
	if( typeof(obj) === 'object' && obj !== null && obj.toString().toLowerCase().indexOf("html") !== -1 )
		return true;
	else
		return false;
};

com_adrianguenter.util.isDOMWindow = function(obj) {
	if( typeof(obj) === 'object' && obj !== null && obj.constructor.toString().toLowerCase().indexOf('window') !== -1 )
		return true;
	else
		return false;
};

com_adrianguenter.util.isNull = function(obj) {
	
	if( typeof(obj) === 'object' && obj === null )
		return true;
	else
		return false;
};

com_adrianguenter.util.require = function(scriptPath,doc) {
	var scriptNode = doc.createElement('script');
	scriptNode.setAttribute('language', 'javascript');
	scriptNode.setAttribute('type', 'text/javascript');
	scriptNode.setAttribute('src', scriptPath);
	doc.getElementsByTagName('head').item(0).appendChild(scriptNode);
	return scriptNode;
};

com_adrianguenter.util.randSec = function(low,high) {
	return (Math.floor((high-(low-1))*Math.random())+low)*1000;
};

com_adrianguenter.util.zeroPad = function(i,places) {
	
	if( i >= 0 ) {
		var negative = false;
		i = i.toString();
	}
	else {
		var negative = true;
		i = i.toString().substr(1);
	}
	
	while( i.length < places ) i = '0'+i;
	
	return ( negative ) ? '-'+i : i;
};

com_adrianguenter.util.MD5 = function(str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: md5('Kevin van Zonneveld');
    // *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
 
    var xl;
 
    var RotateLeft = function(lValue, iShiftBits) {
        return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
    };
 
    var AddUnsigned = function(lX,lY) {
        var lX4,lY4,lX8,lY8,lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
        if (lX4 & lY4) {
            return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        }
        if (lX4 | lY4) {
            if (lResult & 0x40000000) {
                return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            } else {
                return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
            }
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    };
 
    var F = function(x,y,z) { return (x & y) | ((~x) & z); };
    var G = function(x,y,z) { return (x & z) | (y & (~z)); };
    var H = function(x,y,z) { return (x ^ y ^ z); };
    var I = function(x,y,z) { return (y ^ (x | (~z))); };
 
    var FF = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var GG = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var HH = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var II = function(a,b,c,d,x,s,ac) {
        a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
        return AddUnsigned(RotateLeft(a, s), b);
    };
 
    var ConvertToWordArray = function(str) {
        var lWordCount;
        var lMessageLength = str.length;
        var lNumberOfWords_temp1=lMessageLength + 8;
        var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
        var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
        var lWordArray=Array(lNumberOfWords-1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while ( lByteCount < lMessageLength ) {
            lWordCount = (lByteCount-(lByteCount % 4))/4;
            lBytePosition = (lByteCount % 4)*8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount-(lByteCount % 4))/4;
        lBytePosition = (lByteCount % 4)*8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
        lWordArray[lNumberOfWords-2] = lMessageLength<<3;
        lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
        return lWordArray;
    };
 
    var WordToHex = function(lValue) {
        var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
        for (lCount = 0;lCount<=3;lCount++) {
            lByte = (lValue>>>(lCount*8)) & 255;
            WordToHexValue_temp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
        }
        return WordToHexValue;
    };
 
    var x=Array();
    var k,AA,BB,CC,DD,a,b,c,d;
    var S11=7, S12=12, S13=17, S14=22;
    var S21=5, S22=9 , S23=14, S24=20;
    var S31=4, S32=11, S33=16, S34=23;
    var S41=6, S42=10, S43=15, S44=21;
 
    str = com_adrianguenter.util.UTF8.encode(str);
    x = ConvertToWordArray(str);
    a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
    
    xl = x.length;
    for (k=0;k<xl;k+=16) {
        AA=a; BB=b; CC=c; DD=d;
        a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
        d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
        c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
        b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
        a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
        d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
        c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
        b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
        a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
        d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
        c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
        b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
        a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
        d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
        c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
        b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
        a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
        d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
        c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
        b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
        a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
        d=GG(d,a,b,c,x[k+10],S22,0x2441453);
        c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
        b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
        a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
        d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
        c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
        b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
        a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
        d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
        c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
        b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
        a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
        d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
        c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
        b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
        a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
        d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
        c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
        b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
        a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
        d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
        c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
        b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
        a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
        d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
        c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
        b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
        a=II(a,b,c,d,x[k+0], S41,0xF4292244);
        d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
        c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
        b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
        a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
        d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
        c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
        b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
        a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
        d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
        c=II(c,d,a,b,x[k+6], S43,0xA3014314);
        b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
        a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
        d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
        c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
        b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
        a=AddUnsigned(a,AA);
        b=AddUnsigned(b,BB);
        c=AddUnsigned(c,CC);
        d=AddUnsigned(d,DD);
    }
 
    var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
 
    return temp.toLowerCase();
};

com_adrianguenter.util.UTF8 = {

	encode : function(input)
	{
		var output = "";
		
		input = input.replace(/\r\n/g,"\n");
		
		for (var n = 0; n < input.length; n++)
		{
			var c = input.charCodeAt(n);
			
			if (c <= 127)
				output += String.fromCharCode(c);
			else if((c >= 128) && (c <= 2047))
			{
				output += String.fromCharCode((c >> 6) | 192);
				output += String.fromCharCode((c & 63) | 128);
			}
			else
			{
				output += String.fromCharCode((c >> 12) | 224);
				output += String.fromCharCode(((c >> 6) & 63) | 128);
				output += String.fromCharCode((c & 63) | 128);
			}
		}
		return output;
	},
	
	decode : function(input)
	{
		var output = "";
		var i = c = c1 = c2 = 0;
		
		while(i < input.length)
		{
			c = input.charCodeAt(i);
			
			if (c <= 127)
			{
				output += String.fromCharCode(c);
				i++;
			}
			else if((c >= 192) && (c <= 223))
			{
				c2 = input.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else
			{
				c2 = input.charCodeAt(i+1);
				c3 = input.charCodeAt(i+2);
				output += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		return output;
	}
};

com_adrianguenter.util.Base64 = {
 
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
	
	encode : function(input)
	{
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
		
		input = com_adrianguenter.util.UTF8.encode(input);
		
		while (i < input.length)
		{
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);
			
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
			
			if (isNaN(chr2))
				enc3 = enc4 = 64;
			else if (isNaN(chr3))
				enc4 = 64;
			
			output = 
				output+
				this._keyStr.charAt(enc1)+
				this._keyStr.charAt(enc2)+
				this._keyStr.charAt(enc3)+
				this._keyStr.charAt(enc4);
		}
		return output;
	},

	decode : function(input)
	{
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
		
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		
		while (i < input.length)
		{			
			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));
			
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
			
			output = output + String.fromCharCode(chr1);
			
			if (enc3 != 64)
				output = output + String.fromCharCode(chr2);
			
			if (enc4 != 64)
				output = output + String.fromCharCode(chr3);
			
		}
		return com_adrianguenter.util.UTF8.decode(output);
	} 
};

com_adrianguenter.util.arraySortConstructor = function(sortObj) {
	
	var sorter = function(a, b) {
		
		var x, y, order, funcArgs;
		
		for( var i=0; i < sortObj.length; ++i ) {
			
			x = a;
			y = b;
			order = sortObj[i].order;
			funcArgs = [];
			
			for( var j=0; j < sortObj[i].by.length; ++j ) {
				
				x = x[sortObj[i].by[j]];
				y = y[sortObj[i].by[j]];
				
				if( isFunction(x) && isFunction(y) ) {
					
					++j; /* Advance to arg index */
					
					if( typeof(sortObj[i].by[j]) !== 'undefined' && isArray(sortObj[i].by[j]) ) { funcArgs = sortObj[i].by[j]; }
					
					x = x.apply(a,funcArgs);
					y = y.apply(b,funcArgs);
					
					dump(a.name+': '+x+' - '+b.name+': '+y+'\n');
					break;
				}
			}
			
			returnVal = (x < y) ? -1 : ((x > y) ? 1 : 0);
			
			if( returnVal !== 0 ) { break; }
		}
		
		return ( order === 'dsc' ) ? (-1*returnVal) : returnVal;
	};
	
	return sorter;
};

com_adrianguenter.objectQuery = {
	
	select : function(options) {
		
		if( typeof(options) !== 'object' ) { throw new Error('Invalid argument, expected: Object'); }
		
		if( typeof(options.from) !== 'object' ) { throw new Error('Invalid type for `from`, expected: Object'); }
		
		if( typeof(options.where) !== 'undefined' ) {
			
			if( !isObject(options.where) ) { throw new Error('Invalid type for `where`, expected: Object'); }
			
		} else { options.where = {}; } /* Default, returns all */
		
		if( typeof(options.sort) !== 'undefined') {
			
			if( !isObject(options.sort) ) { throw new Error('Invalid type for `sort`, expected: Object or Array wrapped Object(s)'); }
			
			if( !isArray(options.sort) ) options.sort = [options.sort]; /* Wrap single object in array */
			
			for( var i=0; i < options.sort; ++i ) {
				
				if( !isArray(options.sort[i].by) ) { throw new Error('Invalid type for `sort.by`, expected: Array'); }
				
				if( typeof(options.sort[i].order) !== 'undefined') {
					
					if( typeof(options.sort[i].order) !== 'string' || !['asc','dsc'].inArray(options.sort[i].order.toLowerCase()) ) {
						throw new Error('Invalid type or string for `sort.order`, expected: String ("asc" or "dsc")');
					}
					
				} else { options.sort[i].order = 'asc'; } /* Default, ascending */
			}
			
		} else { options.sort = null; } /* Default, uses order of original insertion to parent object */
		
		if( typeof(options.limit) !== 'undefined' ) {
			
			if( !isNumber(options.limit) )
				throw new Error('Invalid type for argument `options.limit`');
			
		} else { options.limit = 0; } /* Default, uncapped */
		
		var results = [];
		var fromObj = options.from;
		
		for( childObj in fromObj ) {
			
			if( !this.match(fromObj[childObj], options.where) ) { continue; }
			
			results.push(fromObj[childObj]);
			
			if( options.limit > 0 && results.length === options.limit ) { break; }
		}
		
		if( results.length > 0 ) {
			
			if( !isNull(options.sort) ) {
				
				var sorter = com_adrianguenter.util.arraySortConstructor(options.sort);
				
				results.sort(sorter);
			}
			
			return results;
			
		} else { return null; }
	},
	
	makeClause : function(clauseArray,replaceArray) {
		
		var validCompOpers = ['==','!=','===','!==','<','<=','>','>='];
		var validLogicOpers = ['&&','||'];
		
		/* [ [ { func : funcReference, args : ['%prop_val%',5,'someotherarg'] }, '<', 'otherval' ],'||',['%prop_val%','!==',true] ] */		
		
		var result, item, operandA, operandB;
		
		if( !isArray(clauseArray) ) { throw new Error('Expected an array clause'); }
		
		if( !isArray(replaceArray) ) {
			
			var replaceArray = [];
			
		} else if( replaceArray.length > 0 && !isArray(replaceArray[0]) ) {
			
			if( replaceArray.length < 2 || isObject(replaceArray[0]) || isObject(replaceArray[1]) ) {
				
				throw new Error('Malformed replaceArray: Expected nested array(s) [[search,replace](, [search,replace], ...)]');
				
			} else {
				
				/* Try to convert single un-nested array ([search,replace]) to proper nest level ([[search,replace]] */
				replaceArray = [[replaceArray[0],replaceArray[1]]];
				
			}
			
		} /* else ... Should be empty array or hopefully correct format here */
		
		if( clauseArray.length === 1 && isString(clauseArray[0]) ) {
			
			/* Eval string clauses */
			var evalString = clauseArray[0];
			var replaceString = '';
			
			for( var j=0; j < replaceArray.length; ++j ) {
				
				
				if( isString(replaceArray[j][1]) ) {
					
					replaceString = '"'+replaceArray[j][1]+'"';
					
				} else { replaceString = replaceArray[j][1]; }
				
				evalString = evalString.replace(replaceArray[j][0],replaceString,'g');
			}
			
			return eval(evalString);
		}
		
		mainIterator:
		for( var i=0; i < clauseArray.length; ++i ) {
			
			item = clauseArray[i];
			
			if( i%2 === 0 ) { /* Even, comparison */
				
				if( isArray(item[0]) ) {
					
					/* Nested clause */
					result = this.makeClause(item, replaceArray);
					
				} else if( item.length === 1 ) { /* Logical unmodified clause: if( __val__ ) ... */
					
					operandA = item[0];
					
					for( var j=0; j < replaceArray.length; ++j ) {
						
						if( operandA === replaceArray[j][0] ) operandA = replaceArray[j][1];
					}
					
					result = (operandA);
					
				} else if( item.length === 2 ) { /* Logical NOT clause: if( !( __val__ ) ) ... */
					
					if( item[0] !== '!' ) {
						throw new Error('Expected logical NOT operator as a string ("!") at index 0 for an array (2) items in length');
					}
					
					operandA = item[1];
					
					for( var j=0; j < replaceArray.length; ++j ) {
						
						if( operandA === replaceArray[j][0] ) operandA = replaceArray[j][1];
					}
					
					result = !(operandA);
					
				} else if( item.length === 3 ) { /* Comparison clause */
					
					if( !validCompOpers.inArray(item[1]) ) { 
						throw new Error('Expected a comparison operator as a string at index 1 for an array (3) items in length');
					}
					
					operandA = item[0];
					operandB = item[2];
					
					for( var j=0; j < replaceArray.length; ++j ) {
						
						if( operandA === replaceArray[j][0] ) operandA = replaceArray[j][1];
						if( operandB === replaceArray[j][0] ) operandB = replaceArray[j][1];
					}
					
					switch( item[1] ) {
						
						case '==': result = (operandA==operandB); break;
						
						case '!=': result = (operandA!=operandB); break;
						
						case '===': result = (operandA===operandB); break;
						
						case '!==': result = (operandA!==operandB); break;
						
						case '<': result = (operandA<operandB); break;
						
						case '<=': result = (operandA<=operandB); break;
						
						case '>': result = (operandA>operandB); break;
						
						case '>=': result = (operandA>=operandB); break;
						
					}
					
				}
				
			} else { /* Odd, OR/AND */
				
				if( !validLogicOpers.inArray(item) ) { 
					throw new Error('Expected a logic operator at the current position in the array');
				}
				
				switch( item ) {
					
					case '&&':
						
						if( !result ) break mainIterator;
						
					break;
					
					case '||':
						
						if( result ) break mainIterator;
						
					break;
					
				}
				
			}
			
		}
		
		return result;
		
	},
	
	match : function(fromObj, searchObj) {
		
		for( searchProp in searchObj ) {
			
			if( typeof(fromObj[searchProp]) === 'undefined' ) { return false; }
			
			if( isArray(searchObj[searchProp]) ) {
				
				if( !this.makeClause(searchObj[searchProp], ['%prop_val%', fromObj[searchProp]]) ) return false;
				
				/* [ [ { func : funcReference, args : ['%prop_val%',5,'someotherarg'] }, '<', 'otherval' ],'||',['%prop_val%','!==',true] ] */
				
			} else if( isObject(searchObj[searchProp]) ) {
				
				if(
					
					   !isObject(fromObj[searchProp])
					|| !this.match(fromObj[searchProp], searchObj[searchProp])
					
				) { return false; }
				
			} else if( fromObj[searchProp] !== searchObj[searchProp] ) { return false; } /* Default comparison - strict equality */
		}
		return true;
	}
	
};

/*}
				else if( isArray(searchObj[searchProp]) ) {
					
					if( !eval(fromObj[searchProp]+' '+searchObj[searchProp][0]+' '+searchObj[searchProp][1]) ) return false;
				*/

/*}
					else if( isArray(searchObj[searchProp]) ) {
						
						// Accept nested arrays here, each nest is basically ( expression) [['<',val],'||',['==',val]&&...?] ... [['<',val],'&&',['>',val]]
						
						if( !eval('('+fromObj[childObj][searchProp]+' '+searchObj[searchProp][0]+' '+searchObj[searchProp][1]+')') ) continue iterateChildren;
					}*/

/*
 * Date Format 1.2.2
 * (c) 2007-2008 Steven Levithan <stevenlevithan.com>
 * MIT license
 * Includes enhancements by Scott Trenda <scott.trenda.net> and Kris Kowal <cixar.com/~kris.kowal/>
 *
 * Accepts a date, a mask, or a date and a mask.
 * Returns a formatted version of the given date.
 * The date defaults to the current date/time.
 * The mask defaults to dateFormat.masks.default.
 
 
var dateFormat = function () {
	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
		timezoneClip = /[^-+\dA-Z]/g,
		pad = function (val, len) {
			val = String(val);
			len = len || 2;
			while (val.length < len) val = "0" + val;
			return val;
		};

	// Regexes and supporting functions are cached through closure
	return function (date, mask, utc) {
		var dF = dateFormat;

		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
		if (arguments.length == 1 && (typeof date == "string" || date instanceof String) && !/\d/.test(date)) {
			mask = date;
			date = undefined;
		}

		// Passing date through Date applies Date.parse, if necessary
		date = date ? new Date(date) : new Date();
		if (isNaN(date)) throw new SyntaxError("invalid date");

		mask = String(dF.masks[mask] || mask || dF.masks["default"]);

		// Allow setting the utc argument via the mask
		if (mask.slice(0, 4) == "UTC:") {
			mask = mask.slice(4);
			utc = true;
		}

		var	_ = utc ? "getUTC" : "get",
			d = date[_ + "Date"](),
			D = date[_ + "Day"](),
			m = date[_ + "Month"](),
			y = date[_ + "FullYear"](),
			H = date[_ + "Hours"](),
			M = date[_ + "Minutes"](),
			s = date[_ + "Seconds"](),
			L = date[_ + "Milliseconds"](),
			o = utc ? 0 : date.getTimezoneOffset(),
			flags = {
				d:    d,
				dd:   pad(d),
				ddd:  dF.i18n.dayNames[D],
				dddd: dF.i18n.dayNames[D + 7],
				m:    m + 1,
				mm:   pad(m + 1),
				mmm:  dF.i18n.monthNames[m],
				mmmm: dF.i18n.monthNames[m + 12],
				yy:   String(y).slice(2),
				yyyy: y,
				h:    H % 12 || 12,
				hh:   pad(H % 12 || 12),
				H:    H,
				HH:   pad(H),
				M:    M,
				MM:   pad(M),
				s:    s,
				ss:   pad(s),
				l:    pad(L, 3),
				L:    pad(L > 99 ? Math.round(L / 10) : L),
				t:    H < 12 ? "a"  : "p",
				tt:   H < 12 ? "am" : "pm",
				T:    H < 12 ? "A"  : "P",
				TT:   H < 12 ? "AM" : "PM",
				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
			};

		return mask.replace(token, function ($0) {
			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
		});
	};
}();

// Some common format strings
dateFormat.masks = {
	"default":      "ddd mmm dd yyyy HH:MM:ss",
	shortDate:      "m/d/yy",
	mediumDate:     "mmm d, yyyy",
	longDate:       "mmmm d, yyyy",
	fullDate:       "dddd, mmmm d, yyyy",
	shortTime:      "h:MM TT",
	mediumTime:     "h:MM:ss TT",
	longTime:       "h:MM:ss TT Z",
	isoDate:        "yyyy-mm-dd",
	isoTime:        "HH:MM:ss",
	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
	dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
	],
	monthNames: [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
	]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
	return dateFormat(this, mask, utc);
};
*/