Browse Source

Prefer TimSort

SukkaW 1 year ago
parent
commit
748861bd2b

+ 2 - 1
Build/build-internal-cdn-rules.ts

@@ -6,6 +6,7 @@ import { task } from './trace';
 import { compareAndWriteFile } from './lib/create-file';
 import { getGorhillPublicSuffixPromise } from './lib/get-gorhill-publicsuffix';
 import { domainDeduper } from './lib/domain-deduper';
+import { sort } from './lib/timsort';
 
 const escapeRegExp = (string = '') => string.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&');
 
@@ -54,7 +55,7 @@ export const buildInternalCDNDomains = task(import.meta.path, async (span) => {
     span,
     [
       ...sortDomains(domainDeduper(Array.from(proxySet)), gorhill).map(i => `SUFFIX,${i}`),
-      ...Array.from(proxyKeywords).sort().map(i => `REGEX,${i}`)
+      ...sort(Array.from(proxyKeywords)).map(i => `REGEX,${i}`)
     ],
     path.resolve(import.meta.dir, '../Internal/cdn.txt')
   );

+ 2 - 1
Build/build-public.ts

@@ -3,6 +3,7 @@ import { task } from './trace';
 import { treeDir } from './lib/tree-dir';
 import type { TreeType, TreeTypeArray } from './lib/tree-dir';
 import listDir from '@sukka/listdir';
+import { sort } from './lib/timsort';
 
 const rootPath = path.resolve(import.meta.dir, '../');
 const publicPath = path.resolve(import.meta.dir, '../public');
@@ -68,7 +69,7 @@ const prioritySorter = (a: TreeType, b: TreeType) => {
 };
 const walk = (tree: TreeTypeArray) => {
   let result = '';
-  tree.sort(prioritySorter);
+  sort(tree, prioritySorter);
   for (let i = 0, len = tree.length; i < len; i++) {
     const entry = tree[i];
     if (entry.type === 'directory') {

+ 2 - 1
Build/build-reject-domainset.ts

@@ -18,6 +18,7 @@ import { getPhishingDomains } from './lib/get-phishing-domains';
 
 import * as SetHelpers from 'mnemonist/set';
 import { setAddFromArray } from './lib/set-add-from-array';
+import { sort } from './lib/timsort';
 
 export const buildRejectDomainSet = task(import.meta.path, async (span) => {
   const gorhill = await getGorhillPublicSuffixPromise();
@@ -155,7 +156,7 @@ export const buildRejectDomainSet = task(import.meta.path, async (span) => {
         return acc;
       }, new Map());
 
-      return Array.from(statMap.entries()).filter(a => a[1] > 9).sort((a, b) => (b[1] - a[1]));
+      return sort(Array.from(statMap.entries()).filter(a => a[1] > 9), (a, b) => (b[1] - a[1]));
     });
 
   const description = [

+ 2 - 0
Build/build-speedtest-domainset.ts

@@ -158,6 +158,8 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async (span) => {
     '.speedtest.aarnet.net.au',
     '.ookla.rcp.net',
     '.ookla-speedtests.e2ro.com',
+    '.speedtest.com.sg',
+    '.ookla.ddnsgeek.com',
     // Cloudflare
     '.speed.cloudflare.com',
     // Wi-Fi Man

+ 27 - 24
Build/lib/create-file.ts

@@ -4,6 +4,7 @@ import { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset
 import picocolors from 'picocolors';
 import type { Span } from '../trace';
 import path from 'path';
+import { sort } from './timsort';
 
 export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string) {
   let isEqual = true;
@@ -122,33 +123,35 @@ const sortTypeOrder: Record<string | typeof defaultSortTypeOrder, number> = {
   'IP-CIDR6': 400
 };
 // sort DOMAIN-SUFFIX and DOMAIN first, then DOMAIN-KEYWORD, then IP-CIDR and IP-CIDR6 if any
-export const sortRuleSet = (ruleSet: string[]) => ruleSet
-  .map((rule) => {
-    const type = collectType(rule);
-    if (!type) {
-      return [10, rule] as const;
-    }
-    if (!(type in sortTypeOrder)) {
-      return [sortTypeOrder[defaultSortTypeOrder], rule] as const;
-    }
-    if (type === 'URL-REGEX') {
-      let extraWeight = 0;
-      if (rule.includes('.+') || rule.includes('.*')) {
-        extraWeight += 10;
+export const sortRuleSet = (ruleSet: string[]) => {
+  return sort(
+    ruleSet.map((rule) => {
+      const type = collectType(rule);
+      if (!type) {
+        return [10, rule] as const;
       }
-      if (rule.includes('|')) {
-        extraWeight += 1;
+      if (!(type in sortTypeOrder)) {
+        return [sortTypeOrder[defaultSortTypeOrder], rule] as const;
       }
+      if (type === 'URL-REGEX') {
+        let extraWeight = 0;
+        if (rule.includes('.+') || rule.includes('.*')) {
+          extraWeight += 10;
+        }
+        if (rule.includes('|')) {
+          extraWeight += 1;
+        }
 
-      return [
-        sortTypeOrder[type] + extraWeight,
-        rule
-      ] as const;
-    }
-    return [sortTypeOrder[type], rule] as const;
-  })
-  .sort((a, b) => a[0] - b[0])
-  .map(c => c[1]);
+        return [
+          sortTypeOrder[type] + extraWeight,
+          rule
+        ] as const;
+      }
+      return [sortTypeOrder[type], rule] as const;
+    }),
+    (a, b) => a[0] - b[0]
+  ).map(c => c[1]);
+};
 
 const MARK = 'this_ruleset_is_made_by_sukkaw.ruleset.skk.moe';
 

+ 5 - 3
Build/lib/timsort.ts

@@ -895,7 +895,7 @@ class TimSort<T> {
  * @param hi - Last element in the range.
  *     comparator.
  */
-export function sort<T>(array: T[], compare: Comparator<T> | undefined = alphabeticalCompare, lo = 0, hi: number = array.length) {
+export function sort<T>(array: T[], compare: Comparator<T> | undefined = alphabeticalCompare, lo = 0, hi: number = array.length): T[] {
   // if (!Array.isArray(array)) {
   //   throw new TypeError('Can only sort arrays');
   // }
@@ -914,7 +914,7 @@ export function sort<T>(array: T[], compare: Comparator<T> | undefined = alphabe
 
   // The array is already sorted
   if (remaining < 2) {
-    return;
+    return array;
   }
 
   let runLength = 0;
@@ -922,7 +922,7 @@ export function sort<T>(array: T[], compare: Comparator<T> | undefined = alphabe
   if (remaining < DEFAULT_MIN_MERGE) {
     runLength = makeAscendingRun(array, lo, hi, compare);
     binaryInsertionSort(array, lo, hi, lo + runLength, compare);
-    return;
+    return array;
   }
 
   const ts = new TimSort(array, compare);
@@ -951,4 +951,6 @@ export function sort<T>(array: T[], compare: Comparator<T> | undefined = alphabe
 
   // Force merging of remaining runs
   ts.forceMergeRuns();
+
+  return array;
 }