• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2// Tar can encode large and negative numbers using a leading byte of
3// 0xff for negative, and 0x80 for positive.
4
5const encode = exports.encode = (num, buf) => {
6  if (!Number.isSafeInteger(num))
7    // The number is so large that javascript cannot represent it with integer
8    // precision.
9    throw TypeError('cannot encode number outside of javascript safe integer range')
10  else if (num < 0)
11    encodeNegative(num, buf)
12  else
13    encodePositive(num, buf)
14  return buf
15}
16
17const encodePositive = (num, buf) => {
18  buf[0] = 0x80
19
20  for (var i = buf.length; i > 1; i--) {
21    buf[i-1] = num & 0xff
22    num = Math.floor(num / 0x100)
23  }
24}
25
26const encodeNegative = (num, buf) => {
27  buf[0] = 0xff
28  var flipped = false
29  num = num * -1
30  for (var i = buf.length; i > 1; i--) {
31    var byte = num & 0xff
32    num = Math.floor(num / 0x100)
33    if (flipped)
34      buf[i-1] = onesComp(byte)
35    else if (byte === 0)
36      buf[i-1] = 0
37    else {
38      flipped = true
39      buf[i-1] = twosComp(byte)
40    }
41  }
42}
43
44const parse = exports.parse = (buf) => {
45  var post = buf[buf.length - 1]
46  var pre = buf[0]
47  var value;
48  if (pre === 0x80)
49    value = pos(buf.slice(1, buf.length))
50  else if (pre === 0xff)
51    value = twos(buf)
52  else
53    throw TypeError('invalid base256 encoding')
54
55  if (!Number.isSafeInteger(value))
56    // The number is so large that javascript cannot represent it with integer
57    // precision.
58    throw TypeError('parsed number outside of javascript safe integer range')
59
60  return value
61}
62
63const twos = (buf) => {
64  var len = buf.length
65  var sum = 0
66  var flipped = false
67  for (var i = len - 1; i > -1; i--) {
68    var byte = buf[i]
69    var f
70    if (flipped)
71      f = onesComp(byte)
72    else if (byte === 0)
73      f = byte
74    else {
75      flipped = true
76      f = twosComp(byte)
77    }
78    if (f !== 0)
79      sum -= f * Math.pow(256, len - i - 1)
80  }
81  return sum
82}
83
84const pos = (buf) => {
85  var len = buf.length
86  var sum = 0
87  for (var i = len - 1; i > -1; i--) {
88    var byte = buf[i]
89    if (byte !== 0)
90      sum += byte * Math.pow(256, len - i - 1)
91  }
92  return sum
93}
94
95const onesComp = byte => (0xff ^ byte) & 0xff
96
97const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
98