| 881 | // A leaf node's `forRange` function returns a new value for this counter, |
| 882 | // unless the operation is to stop early. |
| 883 | forRange<R>( |
| 884 | low: K, |
| 885 | high: K, |
| 886 | includeHigh: boolean | undefined, |
| 887 | editMode: boolean, |
| 888 | tree: BTree<K, V>, |
| 889 | count: number, |
| 890 | onFound?: (k: K, v: V, counter: number) => EditRangeResult<V, R> | void, |
| 891 | ): EditRangeResult<V, R> | number { |
| 892 | const cmp = tree._compare |
| 893 | const keys = this.keys, |
| 894 | children = this.children |
| 895 | let iLow = this.indexOf(low, 0, cmp), |
| 896 | i = iLow |
| 897 | const iHigh = Math.min( |
| 898 | high === low ? iLow : this.indexOf(high, 0, cmp), |
| 899 | keys.length - 1, |
| 900 | ) |
| 901 | if (!editMode) { |
| 902 | // Simple case |
| 903 | for (; i <= iHigh; i++) { |
| 904 | const result = children[i]!.forRange( |
| 905 | low, |
| 906 | high, |
| 907 | includeHigh, |
| 908 | editMode, |
| 909 | tree, |
| 910 | count, |
| 911 | onFound, |
| 912 | ) |
| 913 | if (typeof result !== `number`) return result |
| 914 | count = result |
| 915 | } |
| 916 | } else if (i <= iHigh) { |
| 917 | try { |
| 918 | for (; i <= iHigh; i++) { |
| 919 | if (children[i]!.isShared) children[i] = children[i]!.clone() |
| 920 | const result = children[i]!.forRange( |
| 921 | low, |
| 922 | high, |
| 923 | includeHigh, |
| 924 | editMode, |
| 925 | tree, |
| 926 | count, |
| 927 | onFound, |
| 928 | ) |
| 929 | // Note: if children[i] is empty then keys[i]=undefined. |
| 930 | // This is an invalid state, but it is fixed below. |
| 931 | keys[i] = children[i]!.maxKey()! |
| 932 | if (typeof result !== `number`) return result |
| 933 | count = result |
| 934 | } |
| 935 | } finally { |
| 936 | // Deletions may have occurred, so look for opportunities to merge nodes. |
| 937 | const half = tree._maxNodeSize >> 1 |
| 938 | if (iLow > 0) iLow-- |
| 939 | for (i = iHigh; i >= iLow; i--) { |
| 940 | if (children[i]!.keys.length <= half) { |