# All files / tar/lib large-numbers.js

100% Statements 59/59
100% Branches 20/20
100% Functions 8/8
100% Lines 57/57

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93

    14x
    17x
    17x
    6x

    11x
    17x

    14x
    11x
    11x
    86x
    31x

    55x
    55x

    14x
    6x
    6x
    6x
    6x

    60x
    42x

    18x
    18x

    60x
    48x
    12x
    6x

    6x
    6x

    14x
    47x
    47x
    47x

    14x
    6x
    6x
    6x
    6x
    60x

    60x
    48x
    12x
    6x

    6x
    6x

    60x
    12x

    6x

    14x
    41x
    41x
    41x
    266x
    266x
    161x

    41x

    96x

    14x
     'use strict'
    // Tar can encode large and negative numbers using a leading byte of
    // 0xff for negative, and 0x80 for positive.  The trailing byte in the
    // section will always be 0x20, or in some implementations 0x00.
    // this module encodes and decodes these things.

    const encode = exports.encode = (num, buf) => {
      buf[buf.length - 1] = 0x20
      if (num < 0)
        encodeNegative(num, buf)
      else
        encodePositive(num, buf)
      return buf
    }

    const encodePositive = (num, buf) => {
      buf[0] = 0x80
      for (var i = buf.length - 2; i > 0; i--) {
        if (num === 0)
          buf[i] = 0
        else {
          buf[i] = num % 0x100
          num = Math.floor(num / 0x100)
        }
      }
    }

    const encodeNegative = (num, buf) => {
      buf[0] = 0xff
      var flipped = false
      num = num * -1
      for (var i = buf.length - 2; i > 0; i--) {
        var byte
        if (num === 0)
          byte = 0
        else {
          byte = num % 0x100
          num = Math.floor(num / 0x100)
        }
        if (flipped)
          buf[i] = onesComp(byte)
        else if (byte === 0)
          buf[i] = 0
        else {
          flipped = true
          buf[i] = twosComp(byte)
        }
      }
    }

    const parse = exports.parse = (buf) => {
      var post = buf[buf.length - 1]
      var pre = buf[0]
      return pre === 0x80 ? pos(buf.slice(1, buf.length - 1))
       : twos(buf.slice(1, buf.length - 1))
    }

    const twos = (buf) => {
      var len = buf.length
      var sum = 0
      var flipped = false
      for (var i = len - 1; i > -1; i--) {
        var byte = buf[i]
        var f
        if (flipped)
          f = onesComp(byte)
        else if (byte === 0)
          f = byte
        else {
          flipped = true
          f = twosComp(byte)
        }
        if (f !== 0)
          sum += f * Math.pow(256, len - i - 1)
      }
      return sum * -1
    }

    const pos = (buf) => {
      var len = buf.length
      var sum = 0
      for (var i = len - 1; i > -1; i--) {
        var byte = buf[i]
        if (byte !== 0)
          sum += byte * Math.pow(256, len - i - 1)
      }
      return sum
    }

    const onesComp = byte => (0xff ^ byte) & 0xff

    const twosComp = byte => ((0xff ^ byte) + 1) & 0xff