blob: 04a3b56d870869c29e79131995b30169a33421d1 [file] [log] [blame]
Jeff Thompsondad617b2012-10-14 17:11:41 -07001/*
2 * This class uses BinaryXMLDecoder to follow the structure of a ccnb binary element to
3 * determine its end.
4 *
Jeff Thompson146d7de2012-11-17 16:15:28 -08005 * @author: Jeff Thompson
Jeff Thompsondad617b2012-10-14 17:11:41 -07006 * See COPYING for copyright and distribution information.
7 */
8
9var BinaryXMLStructureDecoder = function BinaryXMLDecoder() {
10 this.gotElementEnd = false;
11 this.offset = 0;
12 this.level = 0;
13 this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
14 this.headerStartOffset = 0;
15 this.readBytesEndOffset = 0;
16};
17
18BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
19BinaryXMLStructureDecoder.READ_BYTES = 1;
20
21/*
22 * Continue scanning input starting from this.offset. If found the end of the element
23 * which started at offset 0 then return true, else false.
24 * If this returns false, you should read more into input and call again.
25 * You have to pass in input each time because the array could be reallocated.
26 * This throws an exception for badly formed ccnb.
27 */
28BinaryXMLStructureDecoder.prototype.findElementEnd = function(
29 // byte array
30 input)
31{
32 if (this.gotElementEnd)
33 // Someone is calling when we already got the end.
34 return true;
35
36 var decoder = new BinaryXMLDecoder(input);
37
38 while (true) {
39 if (this.offset >= input.length)
40 // All the cases assume we have some input.
41 return false;
42
43 switch (this.state) {
44 case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:
45 // First check for XML_CLOSE.
46 if (this.offset == this.headerStartOffset && input[this.offset] == XML_CLOSE) {
47 ++this.offset;
48 // Close the level.
49 --this.level;
50 if (this.level == 0)
51 // Finished.
52 return true;
53 if (this.level < 0)
54 throw new Error("BinaryXMLStructureDecoder: Unexepected close tag at offset " +
55 (this.offset - 1));
56
57 // Get ready for the next header.
58 this.headerStartOffset = this.offset;
59 break;
60 }
61
62 while (true) {
63 if (this.offset >= input.length)
64 return false;
65 if (input[this.offset++] & XML_TT_NO_MORE)
66 // Break and read the header.
67 break;
68 }
69
70 decoder.seek(this.headerStartOffset);
71 var typeAndVal = decoder.decodeTypeAndVal();
72 if (typeAndVal == null)
73 throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
74 this.headerStartOffset);
75
76 // Set the next state based on the type.
77 var type = typeAndVal.t;
78 if (type == XML_DATTR)
79 // We already consumed the item. READ_HEADER_OR_CLOSE again.
80 // ccnb has rules about what must follow an attribute, but we are just scanning.
81 this.headerStartOffset = this.offset;
82 else if (type == XML_DTAG || type == XML_EXT) {
83 // Start a new level and READ_HEADER_OR_CLOSE again.
84 ++this.level;
85 this.headerStartOffset = this.offset;
86 }
87 else if (type == XML_TAG || type == XML_ATTR) {
88 if (type == XML_TAG)
89 // Start a new level and read the tag.
90 ++this.level;
91 // Minimum tag or attribute length is 1.
92 this.readBytesEndOffset = this.offset + typeAndVal.v + 1;
93 this.state = BinaryXMLStructureDecoder.READ_BYTES;
94 // ccnb has rules about what must follow an attribute, but we are just scanning.
95 }
96 else if (type == XML_BLOB || type == XML_UDATA) {
97 this.readBytesEndOffset = this.offset + typeAndVal.v;
98 this.state = BinaryXMLStructureDecoder.READ_BYTES;
99 }
100 else
101 throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
102 break;
103
104 case BinaryXMLStructureDecoder.READ_BYTES:
105 if (input.length < this.readBytesEndOffset) {
106 // Need more.
107 this.offset = input.length;
108 return false;
109 }
110 // Got the bytes. Read a new header or close.
111 this.offset = this.readBytesEndOffset;
112 this.headerStartOffset = this.offset;
113 this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
114 break;
115
116 default:
117 // We don't expect this to happen.
118 throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
119 }
120 }
121};