Added BinaryXMLStructureDecoder. Use it in NDNSocketTransportService to detect the end of the input (instead of the hack to try to decode a ContentObject).
diff --git a/js/encoding/BinaryXMLStructureDecoder.js b/js/encoding/BinaryXMLStructureDecoder.js
new file mode 100644
index 0000000..4ad3de9
--- /dev/null
+++ b/js/encoding/BinaryXMLStructureDecoder.js
@@ -0,0 +1,121 @@
+/*
+ * This class uses BinaryXMLDecoder to follow the structure of a ccnb binary element to
+ * determine its end.
+ *
+ * @author: ucla-cs
+ * See COPYING for copyright and distribution information.
+ */
+
+var BinaryXMLStructureDecoder = function BinaryXMLDecoder() {
+ this.gotElementEnd = false;
+ this.offset = 0;
+ this.level = 0;
+ this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
+ this.headerStartOffset = 0;
+ this.readBytesEndOffset = 0;
+};
+
+BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
+BinaryXMLStructureDecoder.READ_BYTES = 1;
+
+/*
+ * Continue scanning input starting from this.offset. If found the end of the element
+ * which started at offset 0 then return true, else false.
+ * If this returns false, you should read more into input and call again.
+ * You have to pass in input each time because the array could be reallocated.
+ * This throws an exception for badly formed ccnb.
+ */
+BinaryXMLStructureDecoder.prototype.findElementEnd = function(
+ // byte array
+ input)
+{
+ if (this.gotElementEnd)
+ // Someone is calling when we already got the end.
+ return true;
+
+ var decoder = new BinaryXMLDecoder(input);
+
+ while (true) {
+ if (this.offset >= input.length)
+ // All the cases assume we have some input.
+ return false;
+
+ switch (this.state) {
+ case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:
+ // First check for XML_CLOSE.
+ if (this.offset == this.headerStartOffset && input[this.offset] == XML_CLOSE) {
+ ++this.offset;
+ // Close the level.
+ --this.level;
+ if (this.level == 0)
+ // Finished.
+ return true;
+ if (this.level < 0)
+ throw new Error("BinaryXMLStructureDecoder: Unexepected close tag at offset " +
+ (this.offset - 1));
+
+ // Get ready for the next header.
+ this.headerStartOffset = this.offset;
+ break;
+ }
+
+ while (true) {
+ if (this.offset >= input.length)
+ return false;
+ if (input[this.offset++] & XML_TT_NO_MORE)
+ // Break and read the header.
+ break;
+ }
+
+ decoder.seek(this.headerStartOffset);
+ var typeAndVal = decoder.decodeTypeAndVal();
+ if (typeAndVal == null)
+ throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
+ this.headerStartOffset);
+
+ // Set the next state based on the type.
+ var type = typeAndVal.t;
+ if (type == XML_DATTR)
+ // We already consumed the item. READ_HEADER_OR_CLOSE again.
+ // ccnb has rules about what must follow an attribute, but we are just scanning.
+ this.headerStartOffset = this.offset;
+ else if (type == XML_DTAG || type == XML_EXT) {
+ // Start a new level and READ_HEADER_OR_CLOSE again.
+ ++this.level;
+ this.headerStartOffset = this.offset;
+ }
+ else if (type == XML_TAG || type == XML_ATTR) {
+ if (type == XML_TAG)
+ // Start a new level and read the tag.
+ ++this.level;
+ // Minimum tag or attribute length is 1.
+ this.readBytesEndOffset = this.offset + typeAndVal.v + 1;
+ this.state = BinaryXMLStructureDecoder.READ_BYTES;
+ // ccnb has rules about what must follow an attribute, but we are just scanning.
+ }
+ else if (type == XML_BLOB || type == XML_UDATA) {
+ this.readBytesEndOffset = this.offset + typeAndVal.v;
+ this.state = BinaryXMLStructureDecoder.READ_BYTES;
+ }
+ else
+ throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
+ break;
+
+ case BinaryXMLStructureDecoder.READ_BYTES:
+ if (input.length < this.readBytesEndOffset) {
+ // Need more.
+ this.offset = input.length;
+ return false;
+ }
+ // Got the bytes. Read a new header or close.
+ this.offset = this.readBytesEndOffset;
+ this.headerStartOffset = this.offset;
+ this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
+ break;
+
+ default:
+ // We don't expect this to happen.
+ throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
+ }
+ }
+};