diff --git a/index.js b/index.js index 56f7c0b..1d09e26 100644 --- a/index.js +++ b/index.js @@ -44,24 +44,21 @@ function rangeParser (size, str, options) { // 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) + var indexOf = arr[i].indexOf('-') + if (indexOf === -1) { + return -2 + } + + var startStr = arr[i].slice(0, indexOf).trim() + var endStr = arr[i].slice(indexOf + 1).trim() - // -nnn - if (isNaN(start)) { - if (range[0].length > 0) { - return -2 - } + var start = parsePos(startStr) + var end = parsePos(endStr) + if (startStr.length === 0) { start = size - end end = size - 1 - // nnn- - } else if (isNaN(end)) { - if (range[1].length > 0) { - return -2 - } - + } else if (endStr.length === 0) { end = size - 1 } @@ -70,8 +67,12 @@ function rangeParser (size, str, options) { end = size - 1 } + if (isNaN(start) || isNaN(end)) { + return -2 + } + // invalid or unsatisifiable - if (isNaN(start) || isNaN(end) || start > end || start < 0) { + if (start > end || start < 0) { continue } @@ -92,6 +93,16 @@ function rangeParser (size, str, options) { : ranges } +/** + * Parse string to integer. + * @private + */ + +function parsePos (str) { + if (/^\d+$/.test(str)) return Number(str) + return NaN +} + /** * Combine overlapping & adjacent ranges. * @private diff --git a/test/range-parser.js b/test/range-parser.js index 0d75354..f882a93 100644 --- a/test/range-parser.js +++ b/test/range-parser.js @@ -21,6 +21,34 @@ describe('parseRange(len, str)', function () { assert.strictEqual(parse(200, 'bytes=100-x'), -2) }) + it('should return -2 for invalid range format', function () { + assert.strictEqual(parse(200, 'bytes=--100'), -2) + assert.strictEqual(parse(200, 'bytes=100--200'), -2) + assert.strictEqual(parse(200, 'bytes=-'), -2) + assert.strictEqual(parse(200, 'bytes= - '), -2) + }) + + it('should return -2 with multiple dashes in range', function () { + assert.strictEqual(parse(200, 'bytes=100-200-300'), -2) + }) + + it('should return -2 for negative start byte position', function () { + assert.strictEqual(parse(200, 'bytes=-100-150'), -2) + }) + + it('should return -2 for invalid number format', function () { + assert.strictEqual(parse(200, 'bytes=01a-150'), -2) + assert.strictEqual(parse(200, 'bytes=100-15b0'), -2) + }) + + it('should return -1 for unsatisfiable range', function () { + assert.strictEqual(parse(200, 'bytes=500-600'), -1) + }) + + it('should return -1 for unsatisfiable range with multiple ranges', function () { + assert.strictEqual(parse(200, 'bytes=500-600,601-700'), -1) + }) + it('should return -1 if all specified ranges are invalid', function () { assert.strictEqual(parse(200, 'bytes=500-20'), -1) assert.strictEqual(parse(200, 'bytes=500-999'), -1) @@ -99,6 +127,15 @@ describe('parseRange(len, str)', function () { deepEqual(range[0], { start: 0, end: 199 }) }) + it('should parse str with whitespace', function () { + var range = parse(1000, 'bytes= 40-80 , 81-90 , -1 ') + assert.strictEqual(range.type, 'bytes') + assert.strictEqual(range.length, 3) + deepEqual(range[0], { start: 40, end: 80 }) + deepEqual(range[1], { start: 81, end: 90 }) + deepEqual(range[2], { start: 999, end: 999 }) + }) + it('should parse non-byte range', function () { var range = parse(1000, 'items=0-5') assert.strictEqual(range.type, 'items')