| /** |
| * Returns a number indicating whether a reference string comes before, or after, |
| * or is the same as the given string in natural sort order. |
| * |
| * See: https://en.wikipedia.org/wiki/Natural_sort_order |
| * |
| */ |
| export function naturalCompare(aStr, bStr) { |
| let aIndex = 0; |
| let bIndex = 0; |
|
|
| while (aIndex < aStr.length && bIndex < bStr.length) { |
| let aChar = aStr.charCodeAt(aIndex); |
| let bChar = bStr.charCodeAt(bIndex); |
|
|
| if (isDigit(aChar) && isDigit(bChar)) { |
| let aNum = 0; |
|
|
| do { |
| ++aIndex; |
| aNum = aNum * 10 + aChar - DIGIT_0; |
| aChar = aStr.charCodeAt(aIndex); |
| } while (isDigit(aChar) && aNum > 0); |
|
|
| let bNum = 0; |
|
|
| do { |
| ++bIndex; |
| bNum = bNum * 10 + bChar - DIGIT_0; |
| bChar = bStr.charCodeAt(bIndex); |
| } while (isDigit(bChar) && bNum > 0); |
|
|
| if (aNum < bNum) { |
| return -1; |
| } |
|
|
| if (aNum > bNum) { |
| return 1; |
| } |
| } else { |
| if (aChar < bChar) { |
| return -1; |
| } |
|
|
| if (aChar > bChar) { |
| return 1; |
| } |
|
|
| ++aIndex; |
| ++bIndex; |
| } |
| } |
|
|
| return aStr.length - bStr.length; |
| } |
| const DIGIT_0 = 48; |
| const DIGIT_9 = 57; |
|
|
| function isDigit(code) { |
| return !isNaN(code) && DIGIT_0 <= code && code <= DIGIT_9; |
| } |