| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | /*! * 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}
 |