[6a3a178] | 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 |
|
---|
| 5 | const 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 Error('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 |
|
---|
| 17 | const 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 |
|
---|
| 26 | const 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 |
|
---|
| 44 | const parse = (buf) => {
|
---|
| 45 | const pre = buf[0]
|
---|
| 46 | const value = pre === 0x80 ? pos(buf.slice(1, buf.length))
|
---|
| 47 | : pre === 0xff ? twos(buf)
|
---|
| 48 | : null
|
---|
| 49 | if (value === null)
|
---|
| 50 | throw Error('invalid base256 encoding')
|
---|
| 51 |
|
---|
| 52 | if (!Number.isSafeInteger(value))
|
---|
| 53 | // The number is so large that javascript cannot represent it with integer
|
---|
| 54 | // precision.
|
---|
| 55 | throw Error('parsed number outside of javascript safe integer range')
|
---|
| 56 |
|
---|
| 57 | return value
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | const twos = (buf) => {
|
---|
| 61 | var len = buf.length
|
---|
| 62 | var sum = 0
|
---|
| 63 | var flipped = false
|
---|
| 64 | for (var i = len - 1; i > -1; i--) {
|
---|
| 65 | var byte = buf[i]
|
---|
| 66 | var f
|
---|
| 67 | if (flipped)
|
---|
| 68 | f = onesComp(byte)
|
---|
| 69 | else if (byte === 0)
|
---|
| 70 | f = byte
|
---|
| 71 | else {
|
---|
| 72 | flipped = true
|
---|
| 73 | f = twosComp(byte)
|
---|
| 74 | }
|
---|
| 75 | if (f !== 0)
|
---|
| 76 | sum -= f * Math.pow(256, len - i - 1)
|
---|
| 77 | }
|
---|
| 78 | return sum
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 | const pos = (buf) => {
|
---|
| 82 | var len = buf.length
|
---|
| 83 | var sum = 0
|
---|
| 84 | for (var i = len - 1; i > -1; i--) {
|
---|
| 85 | var byte = buf[i]
|
---|
| 86 | if (byte !== 0)
|
---|
| 87 | sum += byte * Math.pow(256, len - i - 1)
|
---|
| 88 | }
|
---|
| 89 | return sum
|
---|
| 90 | }
|
---|
| 91 |
|
---|
| 92 | const onesComp = byte => (0xff ^ byte) & 0xff
|
---|
| 93 |
|
---|
| 94 | const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
|
---|
| 95 |
|
---|
| 96 | module.exports = {
|
---|
| 97 | encode,
|
---|
| 98 | parse,
|
---|
| 99 | }
|
---|