Projekt

Obecné

Profil

Stáhnout (2.83 KB) Statistiky
| Větev: | Revize:
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
}
(4-4/5)