foist
[kismet-logviewer.git] / logviewer / static / js / msgpack.js
1 /* jshint browser: true */
2 /* global define, module */
3 ( // Module boilerplate to support browser globals and browserify and AMD.
4   typeof define === "function" ? function (m) { define("msgpack-js", m); } :
5   typeof exports === "object" ? function (m) { module.exports = m(); } :
6   function(m){ this.msgpack = m(); }
7 )(function () {
8 "use strict";
9
10 var exports = {};
11
12 exports.inspect = inspect;
13 function inspect(buffer) {
14   if (buffer === undefined) return "undefined";
15   var view;
16   var type;
17   if (buffer instanceof ArrayBuffer) {
18     type = "ArrayBuffer";
19     view = new DataView(buffer);
20   }
21   else if (buffer instanceof DataView) {
22     type = "DataView";
23     view = buffer;
24   }
25   if (!view) return JSON.stringify(buffer);
26   var bytes = [];
27   for (var i = 0; i < buffer.byteLength; i++) {
28     if (i > 20) {
29       bytes.push("...");
30       break;
31     }
32     var byte = view.getUint8(i).toString(16);
33     if (byte.length === 1) byte = "0" + byte;
34     bytes.push(byte);
35   }
36   return "<" + type + " " + bytes.join(" ") + ">";
37 }
38
39 // Encode string as utf8 into dataview at offset
40 exports.utf8Write = utf8Write;
41 function utf8Write(view, offset, string) {
42   var byteLength = view.byteLength;
43   for(var i = 0, l = string.length; i < l; i++) {
44     var codePoint = string.charCodeAt(i);
45
46     // One byte of UTF-8
47     if (codePoint < 0x80) {
48       view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
49       continue;
50     }
51
52     // Two bytes of UTF-8
53     if (codePoint < 0x800) {
54       view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
55       view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
56       continue;
57     }
58
59     // Three bytes of UTF-8.
60     if (codePoint < 0x10000) {
61       view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
62       view.setUint8(offset++, codePoint >>> 6  & 0x3f | 0x80);
63       view.setUint8(offset++, codePoint >>> 0  & 0x3f | 0x80);
64       continue;
65     }
66
67     // Four bytes of UTF-8
68     if (codePoint < 0x110000) {
69       view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
70       view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
71       view.setUint8(offset++, codePoint >>> 6  & 0x3f | 0x80);
72       view.setUint8(offset++, codePoint >>> 0  & 0x3f | 0x80);
73       continue;
74     }
75     throw new Error("bad codepoint " + codePoint);
76   }
77 }
78
79 exports.utf8Read = utf8Read;
80 function utf8Read(view, offset, length) {
81   var string = "";
82   for (var i = offset, end = offset + length; i < end; i++) {
83     var byte = view.getUint8(i);
84     // One byte character
85     if ((byte & 0x80) === 0x00) {
86       string += String.fromCharCode(byte);
87       continue;
88     }
89     // Two byte character
90     if ((byte & 0xe0) === 0xc0) {
91       string += String.fromCharCode(
92         ((byte & 0x0f) << 6) |
93         (view.getUint8(++i) & 0x3f)
94       );
95       continue;
96     }
97     // Three byte character
98     if ((byte & 0xf0) === 0xe0) {
99       string += String.fromCharCode(
100         ((byte & 0x0f) << 12) |
101         ((view.getUint8(++i) & 0x3f) << 6) |
102         ((view.getUint8(++i) & 0x3f) << 0)
103       );
104       continue;
105     }
106     // Four byte character
107     if ((byte & 0xf8) === 0xf0) {
108       string += String.fromCharCode(
109         ((byte & 0x07) << 18) |
110         ((view.getUint8(++i) & 0x3f) << 12) |
111         ((view.getUint8(++i) & 0x3f) << 6) |
112         ((view.getUint8(++i) & 0x3f) << 0)
113       );
114       continue;
115     }
116     throw new Error("Invalid byte " + byte.toString(16));
117   }
118   return string;
119 }
120
121 exports.utf8ByteCount = utf8ByteCount;
122 function utf8ByteCount(string) {
123   var count = 0;
124   for(var i = 0, l = string.length; i < l; i++) {
125     var codePoint = string.charCodeAt(i);
126     if (codePoint < 0x80) {
127       count += 1;
128       continue;
129     }
130     if (codePoint < 0x800) {
131       count += 2;
132       continue;
133     }
134     if (codePoint < 0x10000) {
135       count += 3;
136       continue;
137     }
138     if (codePoint < 0x110000) {
139       count += 4;
140       continue;
141     }
142     throw new Error("bad codepoint " + codePoint);
143   }
144   return count;
145 }
146
147 exports.encode = function (value) {
148   var buffer = new ArrayBuffer(encodedSize(value));
149   var view = new DataView(buffer);
150   encode(value, view, 0);
151   return buffer;
152 };
153
154 exports.decode = decode;
155
156 // https://github.com/msgpack/msgpack/blob/master/spec.md
157 // we reserve extension type 0x00 to encode javascript 'undefined'
158
159 function Decoder(view, offset) {
160   this.offset = offset || 0;
161   this.view = view;
162 }
163 Decoder.prototype.map = function (length) {
164   var value = {};
165   for (var i = 0; i < length; i++) {
166     var key = this.parse();
167     value[key] = this.parse();
168   }
169   return value;
170 };
171 Decoder.prototype.bin = function (length) {
172   var value = new ArrayBuffer(length);
173   (new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
174   this.offset += length;
175   return value;
176 };
177 Decoder.prototype.str = function (length) {
178   var value = utf8Read(this.view, this.offset, length);
179   this.offset += length;
180   return value;
181 };
182 Decoder.prototype.array = function (length) {
183   var value = new Array(length);
184   for (var i = 0; i < length; i++) {
185     value[i] = this.parse();
186   }
187   return value;
188 };
189 Decoder.prototype.parse = function () {
190   var type = this.view.getUint8(this.offset);
191   var value, length;
192   // FixStr
193   if ((type & 0xe0) === 0xa0) {
194     length = type & 0x1f;
195     this.offset++;
196     return this.str(length);
197   }
198   // FixMap
199   if ((type & 0xf0) === 0x80) {
200     length = type & 0x0f;
201     this.offset++;
202     return this.map(length);
203   }
204   // FixArray
205   if ((type & 0xf0) === 0x90) {
206     length = type & 0x0f;
207     this.offset++;
208     return this.array(length);
209   }
210   // Positive FixNum
211   if ((type & 0x80) === 0x00) {
212     this.offset++;
213     return type;
214   }
215   // Negative Fixnum
216   if ((type & 0xe0) === 0xe0) {
217     value = this.view.getInt8(this.offset);
218     this.offset++;
219     return value;
220   }
221   // Undefined as FixExt1
222   if (type === 0xd4 && this.view.getUint8(this.offset + 1) === 0x00) {
223     this.offset += 3;
224     return undefined;
225   }
226   switch (type) {
227   // str 8
228   case 0xd9:
229     length = this.view.getUint8(this.offset + 1);
230     this.offset += 2;
231     return this.str(length);
232   // str 16
233   case 0xda:
234     length = this.view.getUint16(this.offset + 1);
235     this.offset += 3;
236     return this.str(length);
237   // str 32
238   case 0xdb:
239     length = this.view.getUint32(this.offset + 1);
240     this.offset += 5;
241     return this.str(length);
242   // bin 8
243   case 0xc4:
244     length = this.view.getUint8(this.offset + 1);
245     this.offset += 2;
246     return this.bin(length);
247   // bin 16
248   case 0xc5:
249     length = this.view.getUint16(this.offset + 1);
250     this.offset += 3;
251     return this.bin(length);
252   // bin 32
253   case 0xc6:
254     length = this.view.getUint32(this.offset + 1);
255     this.offset += 5;
256     return this.bin(length);
257   // nil
258   case 0xc0:
259     this.offset++;
260     return null;
261   // false
262   case 0xc2:
263     this.offset++;
264     return false;
265   // true
266   case 0xc3:
267     this.offset++;
268     return true;
269   // uint8
270   case 0xcc:
271     value = this.view.getUint8(this.offset + 1);
272     this.offset += 2;
273     return value;
274   // uint 16
275   case 0xcd:
276     value = this.view.getUint16(this.offset + 1);
277     this.offset += 3;
278     return value;
279   // uint 32
280   case 0xce:
281     value = this.view.getUint32(this.offset + 1);
282     this.offset += 5;
283     return value;
284   // uint 64
285   case 0xcf:
286     var high = this.view.getUint32(this.offset + 1);
287     var low = this.view.getUint32(this.offset + 5);
288     value = high*0x100000000 + low;
289     this.offset += 9;
290     return value;
291   // int 8
292   case 0xd0:
293     value = this.view.getInt8(this.offset + 1);
294     this.offset += 2;
295     return value;
296   // int 16
297   case 0xd1:
298     value = this.view.getInt16(this.offset + 1);
299     this.offset += 3;
300     return value;
301   // int 32
302   case 0xd2:
303     value = this.view.getInt32(this.offset + 1);
304     this.offset += 5;
305     return value;
306   // int 64
307   case 0xd3:
308     var high = this.view.getInt32(this.offset + 1);
309     var low = this.view.getUint32(this.offset + 5);
310     value = high*0x100000000 + low;
311     this.offset += 9;
312     return value;
313   // map 16
314   case 0xde:
315     length = this.view.getUint16(this.offset + 1);
316     this.offset += 3;
317     return this.map(length);
318   // map 32
319   case 0xdf:
320     length = this.view.getUint32(this.offset + 1);
321     this.offset += 5;
322     return this.map(length);
323   // array 16
324   case 0xdc:
325     length = this.view.getUint16(this.offset + 1);
326     this.offset += 3;
327     return this.array(length);
328   // array 32
329   case 0xdd:
330     length = this.view.getUint32(this.offset + 1);
331     this.offset += 5;
332     return this.array(length);
333   // float
334   case 0xca:
335     value = this.view.getFloat32(this.offset + 1);
336     this.offset += 5;
337     return value;
338   // double
339   case 0xcb:
340     value = this.view.getFloat64(this.offset + 1);
341     this.offset += 9;
342     return value;
343   }
344   throw new Error("Unknown type 0x" + type.toString(16));
345 };
346 function decode(buffer) {
347   var view = new DataView(buffer);
348   var decoder = new Decoder(view);
349   var value = decoder.parse();
350   if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
351   return value;
352 }
353
354 function encode(value, view, offset) {
355   var type = typeof value;
356
357   // Strings Bytes
358   if (type === "string") {
359     var length = utf8ByteCount(value);
360     // fix str
361     if (length < 0x20) {
362       view.setUint8(offset, length | 0xa0);
363       utf8Write(view, offset + 1, value);
364       return 1 + length;
365     }
366     // str 8
367     if (length < 0x100) {
368       view.setUint8(offset, 0xd9);
369       view.setUint8(offset + 1, length);
370       utf8Write(view, offset + 2, value);
371       return 2 + length;
372     }
373     // str 16
374     if (length < 0x10000) {
375       view.setUint8(offset, 0xda);
376       view.setUint16(offset + 1, length);
377       utf8Write(view, offset + 3, value);
378       return 3 + length;
379     }
380     // str 32
381     if (length < 0x100000000) {
382       view.setUint8(offset, 0xdb);
383       view.setUint32(offset + 1, length);
384       utf8Write(view, offset + 5, value);
385       return 5 + length;
386     }
387   }
388
389   if (value instanceof ArrayBuffer) {
390     var length = value.byteLength;
391     // bin 8
392     if (length < 0x100) {
393       view.setUint8(offset, 0xc4);
394       view.setUint8(offset + 1, length);
395       (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 2);
396       return 2 + length;
397     }
398     // bin 16
399     if (length < 0x10000) {
400       view.setUint8(offset, 0xc5);
401       view.setUint16(offset + 1, length);
402       (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
403       return 3 + length;
404     }
405     // bin 32
406     if (length < 0x100000000) {
407       view.setUint8(offset, 0xc6);
408       view.setUint32(offset + 1, length);
409       (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
410       return 5 + length;
411     }
412   }
413
414   if (type === "number") {
415     // Floating Point
416     if ((value << 0) !== value) {
417       view.setUint8(offset, 0xcb);
418       view.setFloat64(offset + 1, value);
419       return 9;
420     }
421
422     // Integers
423     if (value >=0) {
424       // positive fixnum
425       if (value < 0x80) {
426         view.setUint8(offset, value);
427         return 1;
428       }
429       // uint 8
430       if (value < 0x100) {
431         view.setUint8(offset, 0xcc);
432         view.setUint8(offset + 1, value);
433         return 2;
434       }
435       // uint 16
436       if (value < 0x10000) {
437         view.setUint8(offset, 0xcd);
438         view.setUint16(offset + 1, value);
439         return 3;
440       }
441       // uint 32
442       if (value < 0x100000000) {
443         view.setUint8(offset, 0xce);
444         view.setUint32(offset + 1, value);
445         return 5;
446       }
447       throw new Error("Number too big 0x" + value.toString(16));
448     }
449     // negative fixnum
450     if (value >= -0x20) {
451       view.setInt8(offset, value);
452       return 1;
453     }
454     // int 8
455     if (value >= -0x80) {
456       view.setUint8(offset, 0xd0);
457       view.setInt8(offset + 1, value);
458       return 2;
459     }
460     // int 16
461     if (value >= -0x8000) {
462       view.setUint8(offset, 0xd1);
463       view.setInt16(offset + 1, value);
464       return 3;
465     }
466     // int 32
467     if (value >= -0x80000000) {
468       view.setUint8(offset, 0xd2);
469       view.setInt32(offset + 1, value);
470       return 5;
471     }
472     throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
473   }
474
475   // undefined
476   if (type === "undefined") {
477     view.setUint8(offset, 0xd4);  // fixext 1
478     view.setUint8(offset + 1, 0); // type (undefined)
479     view.setUint8(offset + 2, 0); // data (ignored)
480     return 3;
481   }
482
483   // null
484   if (value === null) {
485     view.setUint8(offset, 0xc0);
486     return 1;
487   }
488
489   // Boolean
490   if (type === "boolean") {
491     view.setUint8(offset, value ? 0xc3 : 0xc2);
492     return 1;
493   }
494
495   // Container Types
496   if (type === "object") {
497     var length, size = 0;
498     var isArray = Array.isArray(value);
499
500     if (isArray) {
501       length = value.length;
502     }
503     else {
504       var keys = Object.keys(value);
505       length = keys.length;
506     }
507
508     var size;
509     if (length < 0x10) {
510       view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
511       size = 1;
512     }
513     else if (length < 0x10000) {
514       view.setUint8(offset, isArray ? 0xdc : 0xde);
515       view.setUint16(offset + 1, length);
516       size = 3;
517     }
518     else if (length < 0x100000000) {
519       view.setUint8(offset, isArray ? 0xdd : 0xdf);
520       view.setUint32(offset + 1, length);
521       size = 5;
522     }
523
524     if (isArray) {
525       for (var i = 0; i < length; i++) {
526         size += encode(value[i], view, offset + size);
527       }
528     }
529     else {
530       for (var i = 0; i < length; i++) {
531         var key = keys[i];
532         size += encode(key, view, offset + size);
533         size += encode(value[key], view, offset + size);
534       }
535     }
536
537     return size;
538   }
539   throw new Error("Unknown type " + type);
540 }
541
542 function encodedSize(value) {
543   var type = typeof value;
544
545   // Raw Bytes
546   if (type === "string") {
547     var length = utf8ByteCount(value);
548     if (length < 0x20) {
549       return 1 + length;
550     }
551     if (length < 0x100) {
552       return 2 + length;
553     }
554     if (length < 0x10000) {
555       return 3 + length;
556     }
557     if (length < 0x100000000) {
558       return 5 + length;
559     }
560   }
561
562   if (value instanceof ArrayBuffer) {
563     var length = value.byteLength;
564     if (length < 0x100) {
565       return 2 + length;
566     }
567     if (length < 0x10000) {
568       return 3 + length;
569     }
570     if (length < 0x100000000) {
571       return 5 + length;
572     }
573   }
574
575   if (type === "number") {
576     // Floating Point
577     // double
578     if (value << 0 !== value) return 9;
579
580     // Integers
581     if (value >=0) {
582       // positive fixnum
583       if (value < 0x80) return 1;
584       // uint 8
585       if (value < 0x100) return 2;
586       // uint 16
587       if (value < 0x10000) return 3;
588       // uint 32
589       if (value < 0x100000000) return 5;
590       // uint 64
591       if (value < 0x10000000000000000) return 9;
592       throw new Error("Number too big 0x" + value.toString(16));
593     }
594     // negative fixnum
595     if (value >= -0x20) return 1;
596     // int 8
597     if (value >= -0x80) return 2;
598     // int 16
599     if (value >= -0x8000) return 3;
600     // int 32
601     if (value >= -0x80000000) return 5;
602     // int 64
603     if (value >= -0x8000000000000000) return 9;
604     throw new Error("Number too small -0x" + value.toString(16).substr(1));
605   }
606
607   // undefined
608   if (type === "undefined") return 3;
609
610   // Boolean, null
611   if (type === "boolean" || value === null) return 1;
612
613   // Container Types
614   if (type === "object") {
615     var length, size = 0;
616     if (Array.isArray(value)) {
617       length = value.length;
618       for (var i = 0; i < length; i++) {
619         size += encodedSize(value[i]);
620       }
621     }
622     else {
623       var keys = Object.keys(value);
624       length = keys.length;
625       for (var i = 0; i < length; i++) {
626         var key = keys[i];
627         size += encodedSize(key) + encodedSize(value[key]);
628       }
629     }
630     if (length < 0x10) {
631       return 1 + size;
632     }
633     if (length < 0x10000) {
634       return 3 + size;
635     }
636     if (length < 0x100000000) {
637       return 5 + size;
638     }
639     throw new Error("Array or object too long 0x" + length.toString(16));
640   }
641   throw new Error("Unknown type " + type);
642 }
643
644 return exports;
645
646 });