Latest
Browser interest query
Test file is called index.html
diff --git a/latest/encoding/BinaryXMLEncoder.js b/latest/encoding/BinaryXMLEncoder.js
new file mode 100644
index 0000000..e5039ee
--- /dev/null
+++ b/latest/encoding/BinaryXMLEncoder.js
@@ -0,0 +1,459 @@
+
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+//var BinaryXMLCodec = require('./BinaryXMLCodec').BinaryXMLCodec;
+
+//var codec = new BinaryXMLCodec();
+
+
+var BinaryXMLEncoder = function BinaryXMLEncoder(){
+
+	this.ostream = new Array(1024);
+	
+	this.offset =0;
+	
+	this.CODEC_NAME = "Binary";
+	
+};
+
+
+/*BinaryXMLEncoder.prototype.beginEncoding = function() {
+	this.ostream = new Buffer(1024);
+	this.offset = 0;
+};
+
+BinaryXMLEncoder.prototype.endEncoding = function(){
+	//this.ostream.end();
+};*/
+
+BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content){
+	this.encodeUString(this.ostream, utf8Content);
+};
+
+BinaryXMLEncoder.prototype.writeBlob = function(/*byte []*/ binaryContent
+		//, /*int*/ offset, /*int*/ length
+		)  {
+	//console.log(binaryContent);
+	this.encodeBlob(this.ostream, binaryContent, this.offset, binaryContent.length);
+};
+
+BinaryXMLEncoder.prototype.writeStartElement = function(/*String*/ tag, /*TreeMap<String,String>*/ attributes){
+
+	/*Long*/ dictionaryVal = tag;//stringToTag(tag);
+	
+	if (null == dictionaryVal) {
+
+		this.encodeUString(this.ostream, tag, XML_TAG);
+		
+	} else {
+		this.encodeTypeAndVal(XML_DTAG, dictionaryVal, this.ostream);
+	}
+	
+	if (null != attributes) {
+		this.writeAttributes(attributes); 
+	}
+};
+
+
+BinaryXMLEncoder.prototype.writeEndElement = function(){
+	//console.log(XML_CLOSE);
+	//console.log(tagToString(XML_CLOSE));
+	//this.ostream.writeUInt8(  XML_CLOSE  ,this.offset);
+	this.ostream[this.offset] = XML_CLOSE;
+	this.offset+= 1;
+}
+
+BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
+	
+	if (null == attributes) {
+		return;
+	}
+
+	// the keySet of a TreeMap is sorted.
+	/*Set<String> keySet = attributes.keySet();
+	Iterator<String> it = keySet.iterator();*/
+	
+	for(var i=0; i<attributes.length;i++){
+		var strAttr = attributes[i].k;
+		var strValue = attributes[i].v;
+
+		var dictionaryAttr = stringToTag(strAttr);
+		if (null == dictionaryAttr) {
+			// not in dictionary, encode as attr
+			// compressed format wants length of tag represented as length-1
+			// to save that extra bit, as tag cannot be 0 length.
+			// encodeUString knows to do that.
+			this.encodeUString(this.ostream, strAttr, XML_ATTR);
+		} else {
+			this.encodeTypeAndVal(XML_DATTR, dictionaryAttr, this.ostream);
+		}
+		// Write value
+		this.encodeUString(this.ostream, strValue);
+		
+	}
+
+	
+}
+
+//returns a string
+stringToTag = function(/*long*/ tagVal) {
+	if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
+		return CCNProtocolDTagsStrings[tagVal];
+	} else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
+		return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
+	}
+	return null;
+};
+
+//returns a Long
+tagToString =  function(/*String*/ tagName) {
+	// the slow way, but right now we don't care.... want a static lookup for the forward direction
+	for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
+		if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
+			return i;
+		}
+	}
+	if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
+		return CCNProtocolDTags.CCNProtocolDataUnit;
+	}
+	return null;
+};
+
+
+BinaryXMLEncoder.prototype.writeElement = function(
+		//long 
+		tag, 
+		//byte[] 
+		binaryContent,
+		//TreeMap<String, String> 
+		attributes) {
+	this.writeStartElement(tag, attributes);
+	// Will omit if 0-length
+	
+	this.writeBlob(binaryContent);
+	this.writeEndElement();
+}
+
+//TODO
+//console.log(stringToTag(0));
+
+
+
+
+
+
+
+
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.type = _type;
+	this.val = _val;
+	
+};
+
+
+    
+/*BinaryXMLEncoder.prototype.encodeTypeAndValOffset = function(
+	//int
+	type,
+	//long
+	val,
+	//byte []
+	buf,
+	//int
+	offset) {
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	//int
+	var numEncodingBytes = numEncodingBytes(val);
+	
+	if ((offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+
+	buf[offset + numEncodingBytes - 1] = 
+		(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); 
+	val = val >>> XML_TT_VAL_BITS;;
+	//int
+	var  i = offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= offset)) {
+		buf[i] = (BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); 
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	
+	return numEncodingBytes;
+};*/
+
+//BinaryXMLCodec.prototype.encodeTypeAndVal =  function(
+	//	//final int 
+		//type, 
+		//final long 
+		//value, 
+		//final OutputStream 
+		//ostream,
+		//offset){
+	
+    /*
+    We exploit the fact that encoding is done from the right, so this actually means
+    there is a deterministic encoding from a long to a Type/Value pair:
+    
+    |    0    |    1    |    2    |    3    |    4    |    5    |    6    |    7    |
+    |ABCD.EFGH|IJKL.MNOP|QRST.UVWX|YZ01.2345|6789.abcd|efgh.ijkl|mnop.qrst|uvwx.yz@#
+    
+           60>       53>       46>       39>       32>       25>       18>       11>        4>
+    |_000.ABCD|_EFG.HIJK|_LMN.OPQR|_STU.VWXY|_Z01.2345|_678.9abc|_defg.hij|_klm.nopq|_rst.uvwx|_yz@#___
+    
+    What we want to do is compute the result in MSB order and write it directly
+    to the channel without any intermediate form.
+    */
+
+   //var/*int*/  bits;
+   //var/*int*/  count = 0;
+   
+   // once we start writing bits, we keep writing bits even if they are "0"
+  // var/*bool*/ writing = false;
+   
+   // a few heuristic to catch the small-bit length patterns
+   /*if( value < 0 || value > 15 ) {
+       var start = 60;
+       if( 0 <= value ) {
+    	   if( value < bits_11 )
+    		   start = 4;
+    	   else if( value < bits_18 )
+               start = 11;
+           else if( value < bits_32 )
+               start = 25;
+       }
+       
+       for( var i = start; i >= 4; i -= 7) {
+           bits =  (value >>> i) & BinaryXMLCodec.XML_REG_VAL_MASK;
+           if( bits != 0 || writing ) {
+               ostream.write(bits);
+               count++;
+               writing = true;
+           }
+       }
+   }
+   
+   // Explicit computation of the bottom byte
+   bits = type & BinaryXMLCodec.XML_TT_MASK;
+   var bottom4 = value & BinaryXMLCodec.XML_TT_VAL_MASK;
+   bits |= bottom4 << BinaryXMLCodec.XML_TT_BITS;
+   // the bottom byte always has the NO_MORE flag
+   bits |= BinaryXMLCodec.XML_TT_NO_MORE;
+
+   //console.log(ostream.constructor.name);
+   //console.log(ostream);
+   
+   //ostream.writable = true;
+   //console.log(ostream.)
+   ostream.write(bits.toString());
+   
+   count++;
+
+//	byte [] encoding = encodeTypeAndVal(tag, val);
+//	ostream.write(encoding);
+	return count;
+
+}*/
+
+
+BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
+		//int
+		type, 
+		//long 
+		val, 
+		//byte [] 
+		buf) {
+	
+	console.log('Encoding type '+ type+ ' and value '+ val);
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	var numEncodingBytes = this.numEncodingBytes(val);
+	
+	if ((this.offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-this.offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+	// Bottom 4 bits of val go in last byte with tag.
+	buf[this.offset + numEncodingBytes - 1] = 
+		//(byte)
+			(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); // set top bit for last byte
+	val = val >>> XML_TT_VAL_BITS;;
+	
+	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
+	// is "more" flag.
+	var i = this.offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= this.offset)) {
+		buf[i] = //(byte)
+				(BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); // leave top bit unset
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	if (val != 0) {
+		throw new Exception( "This should not happen: miscalculated encoding");
+		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
+	}
+	this.offset+= numEncodingBytes;
+	console.log('offset increased after tag to  '+this.offset);
+	
+	return numEncodingBytes;
+};
+
+BinaryXMLEncoder.prototype.encodeUString = function(
+		//OutputStream 
+		ostream, 
+		//String 
+		ustring, 
+		//byte 
+		type) {
+	
+	// We elide the encoding of a 0-length UString
+	if ((null == ustring) || (ustring.length == 0)) {
+		//if (Log.isLoggable(Log.FAC_ENCODING, Level.FINER))
+			//Log.finer(Log.FAC_ENCODING, "Eliding 0-length UString.");
+		return;
+	}
+	
+	console.log('Writting String to  '+ ustring);
+	
+	//byte [] data utils
+	/*custom*/
+	//byte[]
+	strBytes = new Array(ustring.Length);
+	var i = 0;
+	for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
+	{
+		strBytes[i] = ustring[i];
+	}
+	//strBytes = DataUtils.getBytesFromUTF8String(ustring);
+	
+	this.encodeTypeAndVal(type, 
+						(((type == XML_TAG) || (type == XML_ATTR)) ?
+								(strBytes.length-1) :
+								strBytes.length), ostream);
+	
+	//console.log(strBytes.toString());
+
+	ostream.write(strBytes.toString(),this.offset);
+	this.offset+= strBytes.length;
+	console.log('offset increased after String to '+this.offset);
+	// 
+};
+
+BinaryXMLEncoder.prototype.encodeBlob = function(
+		//OutputStream 
+		ostream, 
+		//byte [] 
+		blob, 
+		//int 
+		offset, 
+		//int 
+		length) {
+
+	console.log('Writting Blob   ');
+	console.log('length is '+ length);
+	
+	// We elide the encoding of a 0-length blob
+	if ((null == blob) || (length == 0)) {
+
+		return;
+	}
+	
+	
+	this.encodeTypeAndVal(XML_BLOB, length, ostream,offset);
+	
+	if (null != blob) {
+		//console.log(blob);
+		//maybe blog.t
+		ostream.write(blob.toString(), this.offset);
+		this.offset += length;
+		console.log('offset increased after blob to  '+this.offset);
+	}
+};
+
+
+var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
+var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
+var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
+
+BinaryXMLEncoder.prototype.numEncodingBytes = function(
+		//long
+		x) {
+	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
+	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
+	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
+	
+	var numbytes = 1;
+	
+	// Last byte gives you XML_TT_VAL_BITS
+	// Remainder each give you XML_REG_VAL_BITS
+	x = x >>> XML_TT_VAL_BITS;
+	while (x != 0) {
+        numbytes++;
+		x = x >>> XML_REG_VAL_BITS;
+	}
+	return (numbytes);
+};
+
+BinaryXMLEncoder.prototype.writeDateTime = function(
+		//String 
+		tag, 
+		//CCNTime 
+		dateTime) {
+	this.writeElement(tag, dateTime.toBinaryTime());
+};