You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					105 lines
				
				2.2 KiB
			
		
		
			
		
	
	
					105 lines
				
				2.2 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | // Tar can encode large and negative numbers using a leading byte of
 | ||
|  | // 0xff for negative, and 0x80 for positive.
 | ||
|  | 
 | ||
|  | const encode = (num, buf) => { | ||
|  |   if (!Number.isSafeInteger(num)) { | ||
|  |   // The number is so large that javascript cannot represent it with integer
 | ||
|  |   // precision.
 | ||
|  |     throw Error('cannot encode number outside of javascript safe integer range') | ||
|  |   } else if (num < 0) { | ||
|  |     encodeNegative(num, buf) | ||
|  |   } else { | ||
|  |     encodePositive(num, buf) | ||
|  |   } | ||
|  |   return buf | ||
|  | } | ||
|  | 
 | ||
|  | const encodePositive = (num, buf) => { | ||
|  |   buf[0] = 0x80 | ||
|  | 
 | ||
|  |   for (var i = buf.length; i > 1; i--) { | ||
|  |     buf[i - 1] = num & 0xff | ||
|  |     num = Math.floor(num / 0x100) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | const encodeNegative = (num, buf) => { | ||
|  |   buf[0] = 0xff | ||
|  |   var flipped = false | ||
|  |   num = num * -1 | ||
|  |   for (var i = buf.length; i > 1; i--) { | ||
|  |     var byte = num & 0xff | ||
|  |     num = Math.floor(num / 0x100) | ||
|  |     if (flipped) { | ||
|  |       buf[i - 1] = onesComp(byte) | ||
|  |     } else if (byte === 0) { | ||
|  |       buf[i - 1] = 0 | ||
|  |     } else { | ||
|  |       flipped = true | ||
|  |       buf[i - 1] = twosComp(byte) | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | const parse = (buf) => { | ||
|  |   const pre = buf[0] | ||
|  |   const value = pre === 0x80 ? pos(buf.slice(1, buf.length)) | ||
|  |     : pre === 0xff ? twos(buf) | ||
|  |     : null | ||
|  |   if (value === null) { | ||
|  |     throw Error('invalid base256 encoding') | ||
|  |   } | ||
|  | 
 | ||
|  |   if (!Number.isSafeInteger(value)) { | ||
|  |   // The number is so large that javascript cannot represent it with integer
 | ||
|  |   // precision.
 | ||
|  |     throw Error('parsed number outside of javascript safe integer range') | ||
|  |   } | ||
|  | 
 | ||
|  |   return value | ||
|  | } | ||
|  | 
 | ||
|  | 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 | ||
|  | } | ||
|  | 
 | ||
|  | 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 | ||
|  | 
 | ||
|  | module.exports = { | ||
|  |   encode, | ||
|  |   parse, | ||
|  | } |