UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

184 lines (157 loc) 4.22 kB
/** * @author Richard Davey <rich@phaser.io> * @author Angry Bytes (and contributors) * @copyright 2013-2025 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var Device = require('../../device'); /** * The comparator function. * * @ignore * * @param {*} a - The first item to test. * @param {*} b - The second itemt to test. * * @return {boolean} True if they localCompare, otherwise false. */ function Compare (a, b) { return String(a).localeCompare(b); } /** * Process the array contents. * * @ignore * * @param {array} array - The array to process. * @param {function} compare - The comparison function. * * @return {array} - The processed array. */ function Process (array, compare) { // Short-circuit when there's nothing to sort. var len = array.length; if (len <= 1) { return array; } // Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc. // Chunks are the size of the left or right hand in merge sort. // Stop when the left-hand covers all of the array. var buffer = new Array(len); for (var chk = 1; chk < len; chk *= 2) { RunPass(array, compare, chk, buffer); var tmp = array; array = buffer; buffer = tmp; } return array; } /** * Run a single pass with the given chunk size. * * @ignore * * @param {array} arr - The array to run the pass on. * @param {function} comp - The comparison function. * @param {number} chk - The number of iterations. * @param {array} result - The array to store the result in. */ function RunPass (arr, comp, chk, result) { var len = arr.length; var i = 0; // Step size / double chunk size. var dbl = chk * 2; // Bounds of the left and right chunks. var l, r, e; // Iterators over the left and right chunk. var li, ri; // Iterate over pairs of chunks. for (l = 0; l < len; l += dbl) { r = l + chk; e = r + chk; if (r > len) { r = len; } if (e > len) { e = len; } // Iterate both chunks in parallel. li = l; ri = r; while (true) { // Compare the chunks. if (li < r && ri < e) { // This works for a regular `sort()` compatible comparator, // but also for a simple comparator like: `a > b` if (comp(arr[li], arr[ri]) <= 0) { result[i++] = arr[li++]; } else { result[i++] = arr[ri++]; } } else if (li < r) { // Nothing to compare, just flush what's left. result[i++] = arr[li++]; } else if (ri < e) { result[i++] = arr[ri++]; } else { // Both iterators are at the chunk ends. break; } } } } /** * An in-place stable array sort, because `Array#sort()` is not guaranteed stable. * * This is an implementation of merge sort, without recursion. * * Function based on the Two-Screen/stable sort 0.1.8 from https://github.com/Two-Screen/stable * * @function Phaser.Utils.Array.StableSort * @since 3.0.0 * * @param {array} array - The input array to be sorted. * @param {function} [compare] - The comparison function. * * @return {array} The sorted result. */ var StableSort = function (array, compare) { if (compare === undefined) { compare = Compare; } // Short-circuit when there's nothing to sort. if (!array || array.length < 2) { return array; } if (Device.features.stableSort) { return array.sort(compare); } var result = Process(array, compare); // This simply copies back if the result isn't in the original array, which happens on an odd number of passes. if (result !== array) { RunPass(result, null, array.length, array); } return array; }; module.exports = StableSort;