| [81bc7da] | 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 | }
|
|---|
| 15 | return buf
|
|---|
| 16 | }
|
|---|
| 17 |
|
|---|
| 18 | const encodePositive = (num, buf) => {
|
|---|
| 19 | buf[0] = 0x80
|
|---|
| 20 |
|
|---|
| 21 | for (var i = buf.length; i > 1; i--) {
|
|---|
| 22 | buf[i - 1] = num & 0xff
|
|---|
| 23 | num = Math.floor(num / 0x100)
|
|---|
| 24 | }
|
|---|
| 25 | }
|
|---|
| 26 |
|
|---|
| 27 | const encodeNegative = (num, buf) => {
|
|---|
| 28 | buf[0] = 0xff
|
|---|
| 29 | var flipped = false
|
|---|
| 30 | num = num * -1
|
|---|
| 31 | for (var i = buf.length; i > 1; i--) {
|
|---|
| 32 | var byte = num & 0xff
|
|---|
| 33 | num = Math.floor(num / 0x100)
|
|---|
| 34 | if (flipped) {
|
|---|
| 35 | buf[i - 1] = onesComp(byte)
|
|---|
| 36 | } else if (byte === 0) {
|
|---|
| 37 | buf[i - 1] = 0
|
|---|
| 38 | } else {
|
|---|
| 39 | flipped = true
|
|---|
| 40 | buf[i - 1] = twosComp(byte)
|
|---|
| 41 | }
|
|---|
| 42 | }
|
|---|
| 43 | }
|
|---|
| 44 |
|
|---|
| 45 | const parse = (buf) => {
|
|---|
| 46 | const pre = buf[0]
|
|---|
| 47 | const value = pre === 0x80 ? pos(buf.slice(1, buf.length))
|
|---|
| 48 | : pre === 0xff ? twos(buf)
|
|---|
| 49 | : null
|
|---|
| 50 | if (value === null) {
|
|---|
| 51 | throw Error('invalid base256 encoding')
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 | if (!Number.isSafeInteger(value)) {
|
|---|
| 55 | // The number is so large that javascript cannot represent it with integer
|
|---|
| 56 | // precision.
|
|---|
| 57 | throw Error('parsed number outside of javascript safe integer range')
|
|---|
| 58 | }
|
|---|
| 59 |
|
|---|
| 60 | return value
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | const 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 | }
|
|---|
| 82 | return sum
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | const pos = (buf) => {
|
|---|
| 86 | var len = buf.length
|
|---|
| 87 | var sum = 0
|
|---|
| 88 | for (var i = len - 1; i > -1; i--) {
|
|---|
| 89 | var byte = buf[i]
|
|---|
| 90 | if (byte !== 0) {
|
|---|
| 91 | sum += byte * Math.pow(256, len - i - 1)
|
|---|
| 92 | }
|
|---|
| 93 | }
|
|---|
| 94 | return sum
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | const onesComp = byte => (0xff ^ byte) & 0xff
|
|---|
| 98 |
|
|---|
| 99 | const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
|
|---|
| 100 |
|
|---|
| 101 | module.exports = {
|
|---|
| 102 | encode,
|
|---|
| 103 | parse,
|
|---|
| 104 | }
|
|---|