twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

index.js (2900B)


      1 /*!
      2  * range-parser
      3  * Copyright(c) 2012-2014 TJ Holowaychuk
      4  * Copyright(c) 2015-2016 Douglas Christopher Wilson
      5  * MIT Licensed
      6  */
      7 
      8 'use strict'
      9 
     10 /**
     11  * Module exports.
     12  * @public
     13  */
     14 
     15 module.exports = rangeParser
     16 
     17 /**
     18  * Parse "Range" header `str` relative to the given file `size`.
     19  *
     20  * @param {Number} size
     21  * @param {String} str
     22  * @param {Object} [options]
     23  * @return {Array}
     24  * @public
     25  */
     26 
     27 function rangeParser (size, str, options) {
     28   if (typeof str !== 'string') {
     29     throw new TypeError('argument str must be a string')
     30   }
     31 
     32   var index = str.indexOf('=')
     33 
     34   if (index === -1) {
     35     return -2
     36   }
     37 
     38   // split the range string
     39   var arr = str.slice(index + 1).split(',')
     40   var ranges = []
     41 
     42   // add ranges type
     43   ranges.type = str.slice(0, index)
     44 
     45   // parse all ranges
     46   for (var i = 0; i < arr.length; i++) {
     47     var range = arr[i].split('-')
     48     var start = parseInt(range[0], 10)
     49     var end = parseInt(range[1], 10)
     50 
     51     // -nnn
     52     if (isNaN(start)) {
     53       start = size - end
     54       end = size - 1
     55     // nnn-
     56     } else if (isNaN(end)) {
     57       end = size - 1
     58     }
     59 
     60     // limit last-byte-pos to current length
     61     if (end > size - 1) {
     62       end = size - 1
     63     }
     64 
     65     // invalid or unsatisifiable
     66     if (isNaN(start) || isNaN(end) || start > end || start < 0) {
     67       continue
     68     }
     69 
     70     // add range
     71     ranges.push({
     72       start: start,
     73       end: end
     74     })
     75   }
     76 
     77   if (ranges.length < 1) {
     78     // unsatisifiable
     79     return -1
     80   }
     81 
     82   return options && options.combine
     83     ? combineRanges(ranges)
     84     : ranges
     85 }
     86 
     87 /**
     88  * Combine overlapping & adjacent ranges.
     89  * @private
     90  */
     91 
     92 function combineRanges (ranges) {
     93   var ordered = ranges.map(mapWithIndex).sort(sortByRangeStart)
     94 
     95   for (var j = 0, i = 1; i < ordered.length; i++) {
     96     var range = ordered[i]
     97     var current = ordered[j]
     98 
     99     if (range.start > current.end + 1) {
    100       // next range
    101       ordered[++j] = range
    102     } else if (range.end > current.end) {
    103       // extend range
    104       current.end = range.end
    105       current.index = Math.min(current.index, range.index)
    106     }
    107   }
    108 
    109   // trim ordered array
    110   ordered.length = j + 1
    111 
    112   // generate combined range
    113   var combined = ordered.sort(sortByRangeIndex).map(mapWithoutIndex)
    114 
    115   // copy ranges type
    116   combined.type = ranges.type
    117 
    118   return combined
    119 }
    120 
    121 /**
    122  * Map function to add index value to ranges.
    123  * @private
    124  */
    125 
    126 function mapWithIndex (range, index) {
    127   return {
    128     start: range.start,
    129     end: range.end,
    130     index: index
    131   }
    132 }
    133 
    134 /**
    135  * Map function to remove index value from ranges.
    136  * @private
    137  */
    138 
    139 function mapWithoutIndex (range) {
    140   return {
    141     start: range.start,
    142     end: range.end
    143   }
    144 }
    145 
    146 /**
    147  * Sort function to sort ranges by index.
    148  * @private
    149  */
    150 
    151 function sortByRangeIndex (a, b) {
    152   return a.index - b.index
    153 }
    154 
    155 /**
    156  * Sort function to sort ranges by start position.
    157  * @private
    158  */
    159 
    160 function sortByRangeStart (a, b) {
    161   return a.start - b.start
    162 }