(text: string, maxRange?: number)
| 18 | * corresponding to the numbers in that range. It ignores invalid input, sorts it, and removes duplicates |
| 19 | */ |
| 20 | export function parsePageRange(text: string, maxRange?: number): ParsedPageRange { |
| 21 | if (ObjectUtils.isNullOrUndefined(text)) { |
| 22 | return asFailedOperation(""); |
| 23 | } |
| 24 | |
| 25 | text = text.trim(); |
| 26 | |
| 27 | if (text === "") { |
| 28 | return asFailedOperation(""); |
| 29 | } |
| 30 | |
| 31 | let splitText = text.split(","); |
| 32 | let range: number[] = []; |
| 33 | |
| 34 | for (let i = 0; i < splitText.length; ++i) { |
| 35 | let valueToAppend: number[] = [], matches; |
| 36 | let currentValue = splitText[i].trim(); |
| 37 | |
| 38 | if (currentValue === "") { |
| 39 | // We relax the restriction by allowing and ignoring whitespace between commas |
| 40 | continue; |
| 41 | } |
| 42 | |
| 43 | if (/^\d+$/.test(currentValue)) { |
| 44 | let digit = parseInt(currentValue, 10 /* radix */); |
| 45 | if (digit === 0 || !ObjectUtils.isNullOrUndefined(maxRange) && digit > maxRange) { |
| 46 | return asFailedOperation(currentValue); |
| 47 | } |
| 48 | valueToAppend = [digit]; |
| 49 | // ... or it could a range of the form [#]-[#] |
| 50 | } else if (matches = /^(\d+)\s*-\s*(\d+)$/.exec(currentValue)) { |
| 51 | let lhs = parseInt(matches[1], 10), rhs = parseInt(matches[2], 10); |
| 52 | // Try and catch an invalid range as soon as possible, before we compute the range |
| 53 | // We also define a maxRangeAllowed as 2^32, which is the max size of an array in JS |
| 54 | const maxRangeSizeAllowed = 4294967295; |
| 55 | if (lhs >= rhs || lhs === 0 || rhs === 0 || lhs >= maxRangeSizeAllowed || rhs >= maxRangeSizeAllowed || |
| 56 | rhs - lhs + 1 > maxRangeSizeAllowed || (!ObjectUtils.isNullOrUndefined(maxRange) && rhs > maxRange)) { |
| 57 | return asFailedOperation(currentValue); |
| 58 | } |
| 59 | valueToAppend = _.range(lhs, rhs + 1); |
| 60 | } else { |
| 61 | // The currentValue is not a single digit or a valid range |
| 62 | return asFailedOperation(currentValue); |
| 63 | } |
| 64 | |
| 65 | range = range.concat(valueToAppend); |
| 66 | } |
| 67 | |
| 68 | let parsedPageRange = _(range).sortBy().sortedUniq().value(); |
| 69 | |
| 70 | if (parsedPageRange.length === 0) { |
| 71 | return asFailedOperation(text); |
| 72 | } |
| 73 | |
| 74 | const last = _.last(parsedPageRange); |
| 75 | if (!ObjectUtils.isNullOrUndefined(maxRange) && last > maxRange) { |
| 76 | return asFailedOperation(last.toString()); |
| 77 | } |
no test coverage detected