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.
		
		
		
		
		
			
		
			
				
					
					
						
							162 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
	
	
							162 lines
						
					
					
						
							2.8 KiB
						
					
					
				/*! | 
						|
 * range-parser | 
						|
 * Copyright(c) 2012-2014 TJ Holowaychuk | 
						|
 * Copyright(c) 2015-2016 Douglas Christopher Wilson | 
						|
 * MIT Licensed | 
						|
 */ | 
						|
 | 
						|
'use strict' | 
						|
 | 
						|
/** | 
						|
 * Module exports. | 
						|
 * @public | 
						|
 */ | 
						|
 | 
						|
module.exports = rangeParser | 
						|
 | 
						|
/** | 
						|
 * Parse "Range" header `str` relative to the given file `size`. | 
						|
 * | 
						|
 * @param {Number} size | 
						|
 * @param {String} str | 
						|
 * @param {Object} [options] | 
						|
 * @return {Array} | 
						|
 * @public | 
						|
 */ | 
						|
 | 
						|
function rangeParser (size, str, options) { | 
						|
  if (typeof str !== 'string') { | 
						|
    throw new TypeError('argument str must be a string') | 
						|
  } | 
						|
 | 
						|
  var index = str.indexOf('=') | 
						|
 | 
						|
  if (index === -1) { | 
						|
    return -2 | 
						|
  } | 
						|
 | 
						|
  // split the range string | 
						|
  var arr = str.slice(index + 1).split(',') | 
						|
  var ranges = [] | 
						|
 | 
						|
  // add ranges type | 
						|
  ranges.type = str.slice(0, index) | 
						|
 | 
						|
  // parse all ranges | 
						|
  for (var i = 0; i < arr.length; i++) { | 
						|
    var range = arr[i].split('-') | 
						|
    var start = parseInt(range[0], 10) | 
						|
    var end = parseInt(range[1], 10) | 
						|
 | 
						|
    // -nnn | 
						|
    if (isNaN(start)) { | 
						|
      start = size - end | 
						|
      end = size - 1 | 
						|
    // nnn- | 
						|
    } else if (isNaN(end)) { | 
						|
      end = size - 1 | 
						|
    } | 
						|
 | 
						|
    // limit last-byte-pos to current length | 
						|
    if (end > size - 1) { | 
						|
      end = size - 1 | 
						|
    } | 
						|
 | 
						|
    // invalid or unsatisifiable | 
						|
    if (isNaN(start) || isNaN(end) || start > end || start < 0) { | 
						|
      continue | 
						|
    } | 
						|
 | 
						|
    // add range | 
						|
    ranges.push({ | 
						|
      start: start, | 
						|
      end: end | 
						|
    }) | 
						|
  } | 
						|
 | 
						|
  if (ranges.length < 1) { | 
						|
    // unsatisifiable | 
						|
    return -1 | 
						|
  } | 
						|
 | 
						|
  return options && options.combine | 
						|
    ? combineRanges(ranges) | 
						|
    : ranges | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Combine overlapping & adjacent ranges. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function combineRanges (ranges) { | 
						|
  var ordered = ranges.map(mapWithIndex).sort(sortByRangeStart) | 
						|
 | 
						|
  for (var j = 0, i = 1; i < ordered.length; i++) { | 
						|
    var range = ordered[i] | 
						|
    var current = ordered[j] | 
						|
 | 
						|
    if (range.start > current.end + 1) { | 
						|
      // next range | 
						|
      ordered[++j] = range | 
						|
    } else if (range.end > current.end) { | 
						|
      // extend range | 
						|
      current.end = range.end | 
						|
      current.index = Math.min(current.index, range.index) | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  // trim ordered array | 
						|
  ordered.length = j + 1 | 
						|
 | 
						|
  // generate combined range | 
						|
  var combined = ordered.sort(sortByRangeIndex).map(mapWithoutIndex) | 
						|
 | 
						|
  // copy ranges type | 
						|
  combined.type = ranges.type | 
						|
 | 
						|
  return combined | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Map function to add index value to ranges. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function mapWithIndex (range, index) { | 
						|
  return { | 
						|
    start: range.start, | 
						|
    end: range.end, | 
						|
    index: index | 
						|
  } | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Map function to remove index value from ranges. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function mapWithoutIndex (range) { | 
						|
  return { | 
						|
    start: range.start, | 
						|
    end: range.end | 
						|
  } | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Sort function to sort ranges by index. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function sortByRangeIndex (a, b) { | 
						|
  return a.index - b.index | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Sort function to sort ranges by start position. | 
						|
 * @private | 
						|
 */ | 
						|
 | 
						|
function sortByRangeStart (a, b) { | 
						|
  return a.start - b.start | 
						|
}
 | 
						|
 |