/*
ArrayStream.js
Contains functions for serializing/unserializing Javascript arrays
Copyright 2004 Joakim Braun
Author: Joakim Braun (joakim.braun@jfbraun.com)

*/

function dissectArray(inArray){
 	
 	//alert("attempting to dissect array: " + inArray + ", count: "  + inArray.length);
 	
 	var theContents = "Dissected array:\n\n";
 	var theLevel = 0;
	
	theContents += dissectArrayElement(inArray, theLevel);
	
	return theContents;
}

 function dissectArrayElement(inArray, inLevel){
 	
 	var arrayConstructor = new Array().constructor.toString();
 	var theResult = "";
 	var tabs = "";
 	
 	if(inArray)
	{
	for(var i = 0; i < inLevel; i++){
			
		tabs += "\t";	
	}
		
 	for(var i in inArray){
		
		var theType = typeof inArray[i];

		theResult += tabs + "Array element [" + i + "]: ";
		
		if((theType == "array") || (theType == "object")){
 			
 			theResult += "Array:\n" + dissectArrayElement(inArray[i], inLevel + 1);
 		}
 		else
 			theResult += "(" + theType + ") " + inArray[i] + "\n";	
	}
	}
	return theResult;
}

 function serializeArray(inArray){
 	
 	var theResult = "";
 	var ctr = 0;

 	for(var i in inArray){
 		
 		var theType = typeof inArray[i];	
 		var key = escape(i.toString());
 		 		theResult += "key sz:" + key.length + "{" + key + "}";
 		
if((theType == "array") || (theType == "object")){
 			
 			
var arrData = serializeArray(inArray[i]);
 			theResult += "Array sz:" + arrData.length + "{" + arrData + "}";
 			
 		}
 		else{
 			try
			{	
				var str = escape(inArray[i].toString());
 				theResult += theType + " sz:" + str.length + "{" + str + "}";
			}
			catch(theError)
			{
				alert("an error occurred in serializeArray() while accessing the property named " + i);
			}
 		}
 	}
 	
return theResult;

 }
 
 /*
 {number sz:1{0}}{string sz:5{stuff}}{Array sz:2{{string sz:3{duh}}{string sz:3{huh}}}}
 
 that is 
 
 {number sz:1{0}}
 {string sz:5{stuff}}
 {Array sz:2{	{string sz:3{duh}}	{string sz:3{huh}}	}	}
 */
 
 function unserializeArray(inString){
 	
 	var theResult = new Array();
 	var theKey = "";
 	
	if(!inString  || inString == undefined || (inString.length && inString.length == 0))
		return theResult;

	if(!inString.substring){alert("no substring! called by " + unserializeArray.caller);}
	
	
	// Note that arrays with zero entries will come in as "Array sz:0{}".
	// The recursion will then be called with "zero string",
	// which is why we check for inString.length
	while(true && inString.length > 0){
		
		var nextLeftBracketIndex = inString.indexOf("{", 0);	
		var theType = inString.substring(0, inString.indexOf(" ", 0));
		var sizeOffset = inString.indexOf("sz:", 0) + 3;
		var dataSize = parseInt(inString.substring(sizeOffset, nextLeftBracketIndex));
		var theData = inString.substring(nextLeftBracketIndex + 1, nextLeftBracketIndex + 1 + dataSize);
		
		// This will save legacy arrays
		if(theKey == "")
			theKey = theResult.length;
		
		if(theType == "key"){
		
			if(!isNaN(theData)){
				theKey = parseInt(theData);
			}
			else if(theData.length > 0){
				theKey = unescape(theData);
			}
		}
		else if(theType == "number"){
		
			theResult[theKey] = parseFloat(theData);
			theKey = "";
		}
		else if(theType == "string"){
			
			theResult[theKey] = unescape(theData);
			theKey = "";
		}
		else if(theType == "boolean" ){
			
			var val = new Boolean(theData);
			theResult[theKey] = val == true ? true : false;
			theKey = "";
		}
		else if(theType == "Array"){
			
			// Recurse
			//alert("sending array: " + theData);
			theResult[theKey] = unserializeArray(theData);
			theKey = "";
		}
		else{
			
			prompt("Unknown object: " + theType + "\ninString: " + inString, inString);
		}
		
		nextLeftBracketIndex = nextLeftBracketIndex + 2 + dataSize;
		
		if(inString.length - nextLeftBracketIndex > 0){
			inString = inString.substring(nextLeftBracketIndex, nextLeftBracketIndex + (inString.length - nextLeftBracketIndex));
		}
		else
			break;
	}
	
	return theResult;

 }