blob: bf8597b123058545f8e7c9ef0729968958047835 [file] [log] [blame]
Wentao Shangbd63e462012-12-03 16:19:33 -08001/**
Jeff Thompson1b196592012-10-14 17:07:40 -07002 * This class is used to decode ccnb binary elements (blob, type/value pairs).
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07003 *
Jeff Thompson146d7de2012-11-17 16:15:28 -08004 * @author: Meki Cheraoui
Jeff Thompson745026e2012-10-13 12:49:20 -07005 * See COPYING for copyright and distribution information.
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07006 */
7
8var XML_EXT = 0x00;
9
10var XML_TAG = 0x01;
11
12var XML_DTAG = 0x02;
13
14var XML_ATTR = 0x03;
15
16var XML_DATTR = 0x04;
17
18var XML_BLOB = 0x05;
19
20var XML_UDATA = 0x06;
21
22var XML_CLOSE = 0x0;
23
24var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
25
26
27var XML_TT_BITS = 3;
28var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
29var XML_TT_VAL_BITS = XML_TT_BITS + 1;
30var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
31var XML_REG_VAL_BITS = 7;
32var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
33var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
34var BYTE_MASK = 0xFF;
35var LONG_BYTES = 8;
36var LONG_BITS = 64;
37
38var bits_11 = 0x0000007FF;
39var bits_18 = 0x00003FFFF;
40var bits_32 = 0x0FFFFFFFF;
41
42
43
44//returns a string
45tagToString = function(/*long*/ tagVal) {
46 if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
47 return CCNProtocolDTagsStrings[tagVal];
48 } else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
49 return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
50 }
51 return null;
52};
53
54//returns a Long
55stringToTag = function(/*String*/ tagName) {
56 // the slow way, but right now we don't care.... want a static lookup for the forward direction
57 for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
58 if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
59 return i;
60 }
61 }
62 if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
63 return CCNProtocolDTags.CCNProtocolDataUnit;
64 }
65 return null;
66};
67
68//console.log(stringToTag(64));
Jeff Thompson14afeea2013-06-24 16:23:30 -070069var BinaryXMLDecoder = function BinaryXMLDecoder(input){
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070070 var MARK_LEN=512;
71 var DEBUG_MAX_LEN = 32768;
72
Jeff Thompson14afeea2013-06-24 16:23:30 -070073 this.input = input;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070074 this.offset = 0;
75};
76
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070077BinaryXMLDecoder.prototype.initializeDecoding = function() {
Jeff Thompson14afeea2013-06-24 16:23:30 -070078 //if (!this.input.markSupported()) {
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070079 //throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
80 //}
81}
82
83BinaryXMLDecoder.prototype.readStartDocument = function(){
84 // Currently no start document in binary encoding.
85 }
86
87BinaryXMLDecoder.prototype.readEndDocument = function() {
88 // Currently no end document in binary encoding.
89 };
90
91BinaryXMLDecoder.prototype.readStartElement = function(
92 //String
93 startTag,
94 //TreeMap<String, String>
95 attributes) {
96
97
98 //NOT SURE
99 //if(typeof startTag == 'number')
100 //startTag = tagToString(startTag);
101
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700102 //TypeAndVal
Jeff Thompsonc3c611b2013-02-18 22:52:03 -0800103 var tv = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700104
105 if (null == tv) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700106 throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got something not a tag."));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700107 }
108
109 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800110 var decodedTag = null;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700111 //console.log(tv);
112 //console.log(typeof tv);
113
114 //console.log(XML_TAG);
115 if (tv.type() == XML_TAG) {
116 //console.log('got here');
117 //Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
118 // Tag value represents length-1 as tags can never be empty.
119 var valval ;
120 if(typeof tv.val() == 'string'){
121 valval = (parseInt(tv.val())) + 1;
122 }
123 else
124 valval = (tv.val())+ 1;
125
126 //console.log('valval is ' +valval);
127
Jeff Thompson1b196592012-10-14 17:07:40 -0700128 decodedTag = this.decodeUString(valval);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700129
130 } else if (tv.type() == XML_DTAG) {
131 //console.log('gothere');
132 //console.log(tv.val());
133 //decodedTag = tagToString(tv.val());
134 //console.log()
135 decodedTag = tv.val();
136 }
137
138 //console.log(decodedTag);
139 //console.log('startTag is '+startTag);
140
141
142 if ((null == decodedTag) || decodedTag != startTag ) {
Jeff Thompsonb7e190b2012-11-28 18:38:15 -0800143 console.log('expecting '+ startTag + ' but got '+ decodedTag);
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700144 throw new ContentDecodingException(new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")"));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700145 }
146
147 // DKS: does not read attributes out of stream if caller doesn't
148 // ask for them. Should possibly peek and skip over them regardless.
149 // TODO: fix this
150 if (null != attributes) {
151 readAttributes(attributes);
152 }
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700153 }
154
155
156BinaryXMLDecoder.prototype.readAttributes = function(
Jeff Thompsonc3c611b2013-02-18 22:52:03 -0800157 // array of [attributeName, attributeValue]
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700158 attributes) {
159
160 if (null == attributes) {
161 return;
162 }
163
164 try {
165 // Now need to get attributes.
166 //TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800167 var nextTV = this.peekTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700168
169 while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
170 (XML_DATTR == nextTV.type()))) {
171
172 // Decode this attribute. First, really read the type and value.
173 //this.TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800174 var thisTV = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700175
176 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800177 var attributeName = null;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700178 if (XML_ATTR == thisTV.type()) {
179 // Tag value represents length-1 as attribute names cannot be empty.
180 var valval ;
Jeff Thompsonc3c611b2013-02-18 22:52:03 -0800181 if(typeof thisTV.val() == 'string'){
182 valval = (parseInt(thisTV.val())) + 1;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700183 }
184 else
Jeff Thompsonc3c611b2013-02-18 22:52:03 -0800185 valval = (thisTV.val())+ 1;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700186
Jeff Thompson1b196592012-10-14 17:07:40 -0700187 attributeName = this.decodeUString(valval);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700188
189 } else if (XML_DATTR == thisTV.type()) {
190 // DKS TODO are attributes same or different dictionary?
191 attributeName = tagToString(thisTV.val());
192 if (null == attributeName) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700193 throw new ContentDecodingException(new Error("Unknown DATTR value" + thisTV.val()));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700194 }
195 }
196 // Attribute values are always UDATA
197 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800198 var attributeValue = this.decodeUString();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700199
200 //
201 attributes.push([attributeName, attributeValue]);
202
Jeff Thompson1b196592012-10-14 17:07:40 -0700203 nextTV = this.peekTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700204 }
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700205 } catch ( e) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700206 throw new ContentDecodingException(new Error("readStartElement", e));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700207 }
208};
209
210//returns a string
211BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
Jeff Thompson14afeea2013-06-24 16:23:30 -0700212 //this.input.mark(MARK_LEN);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700213
214 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800215 var decodedTag = null;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700216 var previousOffset = this.offset;
217 try {
218 // Have to distinguish genuine errors from wrong tags. Could either use
219 // a special exception subtype, or redo the work here.
220 //this.TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800221 var tv = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700222
223 if (null != tv) {
224
225 if (tv.type() == XML_TAG) {
226 /*if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700227 throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!")(;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700228 }*/
229
230 // Tag value represents length-1 as tags can never be empty.
231 var valval ;
232 if(typeof tv.val() == 'string'){
233 valval = (parseInt(tv.val())) + 1;
234 }
235 else
236 valval = (tv.val())+ 1;
237
Jeff Thompson1b196592012-10-14 17:07:40 -0700238 decodedTag = this.decodeUString(valval);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700239
240 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
241
242 } else if (tv.type() == XML_DTAG) {
243 decodedTag = tagToString(tv.val());
244 }
245
246 } // else, not a type and val, probably an end element. rewind and return false.
247
248 } catch ( e) {
249
250 } finally {
251 try {
252 this.offset = previousOffset;
253 } catch ( e) {
254 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700255 throw new ContentDecodingException(new Error("Cannot reset stream! " + e.getMessage(), e));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700256 }
257 }
258 return decodedTag;
259};
260
261BinaryXMLDecoder.prototype.peekStartElement = function(
262 //String
263 startTag) {
264 //String
265 if(typeof startTag == 'string'){
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800266 var decodedTag = this.peekStartElementAsString();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700267
268 if ((null != decodedTag) && decodedTag == startTag) {
269 return true;
270 }
271 return false;
272 }
273 else if(typeof startTag == 'number'){
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800274 var decodedTag = this.peekStartElementAsLong();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700275 if ((null != decodedTag) && decodedTag == startTag) {
276 return true;
277 }
278 return false;
279 }
280 else{
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700281 throw new ContentDecodingException(new Error("SHOULD BE STRING OR NUMBER"));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700282 }
283}
284//returns Long
285BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
Jeff Thompson14afeea2013-06-24 16:23:30 -0700286 //this.input.mark(MARK_LEN);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700287
288 //Long
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800289 var decodedTag = null;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700290
291 var previousOffset = this.offset;
292
293 try {
294 // Have to distinguish genuine errors from wrong tags. Could either use
295 // a special exception subtype, or redo the work here.
296 //this.TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800297 var tv = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700298
299 if (null != tv) {
300
301 if (tv.type() == XML_TAG) {
302 if (tv.val()+1 > DEBUG_MAX_LEN) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700303 throw new ContentDecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!"));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700304 }
305
306 var valval ;
307 if(typeof tv.val() == 'string'){
308 valval = (parseInt(tv.val())) + 1;
309 }
310 else
311 valval = (tv.val())+ 1;
312
313 // Tag value represents length-1 as tags can never be empty.
314 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800315 var strTag = this.decodeUString(valval);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700316
317 decodedTag = stringToTag(strTag);
318
319 //Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
320
321 } else if (tv.type() == XML_DTAG) {
322 decodedTag = tv.val();
323 }
324
325 } // else, not a type and val, probably an end element. rewind and return false.
326
327 } catch ( e) {
328
329 } finally {
330 try {
Jeff Thompson14afeea2013-06-24 16:23:30 -0700331 //this.input.reset();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700332 this.offset = previousOffset;
333 } catch ( e) {
334 Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
Jeff Thompson34a2ec02012-09-29 21:47:05 -0700335 throw new Error("Cannot reset stream! " + e.getMessage(), e);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700336 }
337 }
338 return decodedTag;
339 };
340
341
Jeff Thompsonefff43b2013-03-10 17:10:26 -0700342// Returns a Uint8Array.
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700343BinaryXMLDecoder.prototype.readBinaryElement = function(
344 //long
345 startTag,
346 //TreeMap<String, String>
Jeff Thompsond4a1f862013-03-10 17:30:31 -0700347 attributes,
348 //boolean
349 allowNull){
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800350 this.readStartElement(startTag, attributes);
Jeff Thompsond4a1f862013-03-10 17:30:31 -0700351 return this.readBlob(allowNull);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700352};
353
354
355BinaryXMLDecoder.prototype.readEndElement = function(){
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700356 if(LOG>4)console.log('this.offset is '+this.offset);
357
Jeff Thompson14afeea2013-06-24 16:23:30 -0700358 var next = this.input[this.offset];
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700359
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700360 this.offset++;
361 //read();
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700362
363 if(LOG>4)console.log('XML_CLOSE IS '+XML_CLOSE);
364 if(LOG>4)console.log('next is '+next);
365
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700366 if (next != XML_CLOSE) {
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700367 console.log("Expected end element, got: " + next);
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700368 throw new ContentDecodingException(new Error("Expected end element, got: " + next));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700369 }
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700370 };
371
372
373//String
374BinaryXMLDecoder.prototype.readUString = function(){
375 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800376 var ustring = this.decodeUString();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700377 this.readEndElement();
378 return ustring;
379
380 };
381
382
Jeff Thompsond4a1f862013-03-10 17:30:31 -0700383/*
384 * Read a blob as well as the end element. Returns a Uint8Array (or null for missing blob).
385 * If the blob is missing and allowNull is false (default), throw an exception. Otherwise,
386 * just read the end element and return null.
387 */
388BinaryXMLDecoder.prototype.readBlob = function(allowNull) {
Jeff Thompson14afeea2013-06-24 16:23:30 -0700389 if (this.input[this.offset] == XML_CLOSE && allowNull) {
Jeff Thompsond4a1f862013-03-10 17:30:31 -0700390 this.readEndElement();
391 return null;
392 }
393
Jeff Thompsonefff43b2013-03-10 17:10:26 -0700394 var blob = this.decodeBlob();
395 this.readEndElement();
396 return blob;
397};
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700398
399
400//CCNTime
401BinaryXMLDecoder.prototype.readDateTime = function(
402 //long
403 startTag) {
404 //byte []
405
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700406 var byteTimestamp = this.readBinaryElement(startTag);
407
408 //var lontimestamp = DataUtils.byteArrayToUnsignedLong(byteTimestamp);
409
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800410 byteTimestamp = DataUtils.toHex(byteTimestamp);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700411
412
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800413 byteTimestamp = parseInt(byteTimestamp, 16);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700414
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800415 var lontimestamp = (byteTimestamp/ 4096) * 1000;
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700416
417 //if(lontimestamp<0) lontimestamp = - lontimestamp;
418
Jeff Thompson0da65612013-03-10 16:30:27 -0700419 if(LOG>4) console.log('DECODED DATE WITH VALUE');
420 if(LOG>4) console.log(lontimestamp);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700421
422
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700423 //CCNTime
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800424 var timestamp = new CCNTime(lontimestamp);
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700425 //timestamp.setDateBinary(byteTimestamp);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700426
427 if (null == timestamp) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700428 throw new ContentDecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700429 }
430 return timestamp;
431};
432
Jeff Thompson1b196592012-10-14 17:07:40 -0700433BinaryXMLDecoder.prototype.decodeTypeAndVal = function() {
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700434
Jeff Thompsonf72d7ed2012-10-25 20:57:07 -0700435 /*int*/var type = -1;
436 /*long*/var val = 0;
437 /*boolean*/var more = true;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700438
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700439 do {
440
Jeff Thompson14afeea2013-06-24 16:23:30 -0700441 var next = this.input[this.offset ];
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700442
443
444 if (next < 0) {
445 return null;
446 }
447
448 if ((0 == next) && (0 == val)) {
449 return null;
450 }
451
452 more = (0 == (next & XML_TT_NO_MORE));
453
454 if (more) {
455 val = val << XML_REG_VAL_BITS;
456 val |= (next & XML_REG_VAL_MASK);
457 } else {
458
459 type = next & XML_TT_MASK;
460 val = val << XML_TT_VAL_BITS;
461 val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
462 }
463
464 this.offset++;
465
466 } while (more);
467
Jeff Thompson0da65612013-03-10 16:30:27 -0700468 if(LOG>4)console.log('TYPE is '+ type + ' VAL is '+ val);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700469
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700470 return new TypeAndVal(type, val);
471};
472
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700473//TypeAndVal
Jeff Thompson7480aca2013-03-10 16:01:33 -0700474BinaryXMLDecoder.prototype.peekTypeAndVal = function() {
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700475 //TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800476 var tv = null;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700477 var previousOffset = this.offset;
478
479 try {
Jeff Thompson1b196592012-10-14 17:07:40 -0700480 tv = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700481 } finally {
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700482 this.offset = previousOffset;
483 }
484
485 return tv;
486};
487
Jeff Thompsonc92706b2012-11-11 19:12:58 -0800488//Uint8Array
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700489BinaryXMLDecoder.prototype.decodeBlob = function(
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700490 //int
491 blobLength) {
492
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700493 if(null == blobLength){
494 //TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800495 var tv = this.decodeTypeAndVal();
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700496
497 var valval ;
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700498
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700499 if(typeof tv.val() == 'string'){
500 valval = (parseInt(tv.val()));
501 }
502 else
503 valval = (tv.val());
504
505 //console.log('valval here is ' + valval);
Jeff Thompson1b196592012-10-14 17:07:40 -0700506 return this.decodeBlob(valval);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700507 }
508
509 //
Jeff Thompsonc92706b2012-11-11 19:12:58 -0800510 //Uint8Array
Jeff Thompson14afeea2013-06-24 16:23:30 -0700511 var bytes = this.input.subarray(this.offset, this.offset+ blobLength);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700512 this.offset += blobLength;
513
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700514 return bytes;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700515};
516
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700517//String
518BinaryXMLDecoder.prototype.decodeUString = function(
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700519 //int
520 byteLength) {
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700521 if(null == byteLength ){
522 var tempStreamPosition = this.offset;
523
524 //TypeAndVal
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800525 var tv = this.decodeTypeAndVal();
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700526
Jeff Thompson0da65612013-03-10 16:30:27 -0700527 if(LOG>4)console.log('TV is '+tv);
528 if(LOG>4)console.log(tv);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700529
Jeff Thompson0da65612013-03-10 16:30:27 -0700530 if(LOG>4)console.log('Type of TV is '+typeof tv);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700531
532 if ((null == tv) || (XML_UDATA != tv.type())) { // if we just have closers left, will get back null
533 //if (Log.isLoggable(Log.FAC_ENCODING, Level.FINEST))
534 //Log.finest(Log.FAC_ENCODING, "Expected UDATA, got " + ((null == tv) ? " not a tag " : tv.type()) + ", assuming elided 0-length blob.");
535
536 this.offset = tempStreamPosition;
537
538 return "";
539 }
540
Jeff Thompson1b196592012-10-14 17:07:40 -0700541 return this.decodeUString(tv.val());
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700542 }
543 else{
Wentao Shang882e34e2013-01-05 02:49:51 -0800544 //uint8array
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800545 var stringBytes = this.decodeBlob(byteLength);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700546
547 //return DataUtils.getUTF8StringFromBytes(stringBytes);
548 return DataUtils.toString(stringBytes);
549
550 }
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700551};
552
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700553//OBject containg a pair of type and value
554var TypeAndVal = function TypeAndVal(_type,_val) {
555 this.t = _type;
556 this.v = _val;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700557};
558
559TypeAndVal.prototype.type = function(){
560 return this.t;
561};
562
563TypeAndVal.prototype.val = function(){
564 return this.v;
565};
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700566
567
568
569
570BinaryXMLDecoder.prototype.readIntegerElement =function(
571 //String
572 startTag) {
573
574 //String
575 if(LOG>4) console.log('READING INTEGER '+ startTag);
576 if(LOG>4) console.log('TYPE OF '+ typeof startTag);
577
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800578 var strVal = this.readUTF8Element(startTag);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700579
580 return parseInt(strVal);
581};
582
583
584BinaryXMLDecoder.prototype.readUTF8Element =function(
585 //String
586 startTag,
587 //TreeMap<String, String>
588 attributes) {
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700589 //throws Error where name == "ContentDecodingException"
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700590
591 this.readStartElement(startTag, attributes); // can't use getElementText, can't get attributes
592 //String
Jeff Thompson41ef0f92012-11-24 09:22:55 -0800593 var strElementText = this.readUString();
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700594 return strElementText;
595};
Jeff Thompson1b196592012-10-14 17:07:40 -0700596
Jeff Thompsonc92706b2012-11-11 19:12:58 -0800597
Jeff Thompson1b196592012-10-14 17:07:40 -0700598/*
599 * Set the offset into the input, used for the next read.
600 */
601BinaryXMLDecoder.prototype.seek = function(
602 //int
603 offset) {
Jeff Thompsonc92706b2012-11-11 19:12:58 -0800604 this.offset = offset;
Jeff Thompson1b196592012-10-14 17:07:40 -0700605}
Jeff Thompsoncab74c32012-10-21 13:27:28 -0700606
607/*
608 * Call with: throw new ContentDecodingException(new Error("message")).
609 */
610function ContentDecodingException(error) {
611 this.message = error.message;
612 // Copy lineNumber, etc. from where new Error was called.
613 for (var prop in error)
614 this[prop] = error[prop];
615}
616ContentDecodingException.prototype = new Error();
617ContentDecodingException.prototype.name = "ContentDecodingException";
618