Skip to content

Commit

Permalink
add compareSubstring, compareSubstringIgnoreCase and adopt for search…
Browse files Browse the repository at this point in the history
… tree so that it will be fit for case-in-sensitive compare, #93368
  • Loading branch information
jrieken committed Apr 8, 2020
1 parent 5c9a1b5 commit 182e906
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 39 deletions.
35 changes: 10 additions & 25 deletions src/vs/base/common/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { URI } from 'vs/base/common/uri';
import { CharCode } from 'vs/base/common/charCode';
import { compareIgnoreCase, compare } from 'vs/base/common/strings';
import { compareSubstringIgnoreCase, compare, compareSubstring } from 'vs/base/common/strings';

/**
* @deprecated ES6: use `[...SetOrMap.values()]`
Expand Down Expand Up @@ -102,7 +102,10 @@ export class PathIterator implements IKeyIterator<string> {
private _from!: number;
private _to!: number;

constructor(private _splitOnBackslash: boolean = true) { }
constructor(
private readonly _splitOnBackslash: boolean = true,
private readonly _caseSensitive: boolean = true
) { }

reset(key: string): this {
this._value = key.replace(/\\$|\/$/, '');
Expand Down Expand Up @@ -135,27 +138,9 @@ export class PathIterator implements IKeyIterator<string> {
}

cmp(a: string): number {

let aPos = 0;
const aLen = a.length;
let thisPos = this._from;

while (aPos < aLen && thisPos < this._to) {
const cmp = a.charCodeAt(aPos) - this._value.charCodeAt(thisPos);
if (cmp !== 0) {
return cmp;
}
aPos += 1;
thisPos += 1;
}

if (aLen === this._to - this._from) {
return 0;
} else if (aPos < aLen) {
return -1;
} else {
return 1;
}
return this._caseSensitive
? compareSubstring(a, this._value, 0, a.length, this._from, this._to)
: compareSubstringIgnoreCase(a, this._value, 0, a.length, this._from, this._to);
}

value(): string {
Expand Down Expand Up @@ -215,9 +200,9 @@ export class UriIterator implements IKeyIterator<URI> {

cmp(a: string): number {
if (this._states[this._stateIdx] === UriIteratorState.Scheme) {
return compareIgnoreCase(a, this._value.scheme);
return compareSubstringIgnoreCase(a, this._value.scheme);
} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {
return compareIgnoreCase(a, this._value.authority);
return compareSubstringIgnoreCase(a, this._value.authority);
} else if (this._states[this._stateIdx] === UriIteratorState.Path) {
return this._pathIterator.cmp(a);
} else if (this._states[this._stateIdx] === UriIteratorState.Query) {
Expand Down
44 changes: 31 additions & 13 deletions src/vs/base/common/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,31 @@ export function compare(a: string, b: string): number {
}
}

export function compareIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
export function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
let codeA = a.charCodeAt(aStart);
let codeB = b.charCodeAt(bStart);
if (codeA < codeB) {
return -1;
} else if (codeA > codeB) {
return 1;
}
}
const aLen = aEnd - aStart;
const bLen = bEnd - bStart;
if (aLen < bLen) {
return -1;
} else if (aLen > bLen) {
return 1;
}
return 0;
}

export function compareIgnoreCase(a: string, b: string): number {
return compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);
}

export function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {

for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {

Expand All @@ -307,26 +331,20 @@ export function compareIgnoreCase(a: string, b: string, aStart: number = 0, aEnd
continue;
}

if (isUpperAsciiLetter(codeA)) {
codeA += 32;
}

if (isUpperAsciiLetter(codeB)) {
codeB += 32;
}

const diff = codeA - codeB;
if (diff === 32 && isUpperAsciiLetter(codeB)) { //codeB =[65-90] && codeA =[97-122]
continue;

if (diff === 0) {
// equal -> ignoreCase
} else if (diff === -32 && isUpperAsciiLetter(codeA)) { //codeB =[97-122] && codeA =[65-90]
continue;
}

} else if (isLowerAsciiLetter(codeA) && isLowerAsciiLetter(codeB)) {
if (isLowerAsciiLetter(codeA) && isLowerAsciiLetter(codeB)) {
//
return diff;

} else {
return compare(a.toLowerCase(), b.toLowerCase());
return compareSubstring(a.toLowerCase(), b.toLowerCase(), aStart, aEnd, bStart, bEnd);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/vs/base/test/common/strings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ suite('Strings', () => {
test('compareIgnoreCase (substring)', () => {

function assertCompareIgnoreCase(a: string, b: string, aStart: number, aEnd: number, bStart: number, bEnd: number, recurse = true): void {
let actual = strings.compareIgnoreCase(a, b, aStart, aEnd, bStart, bEnd);
let actual = strings.compareSubstringIgnoreCase(a, b, aStart, aEnd, bStart, bEnd);
actual = actual > 0 ? 1 : actual < 0 ? -1 : actual;

let expected = strings.compare(a.toLowerCase().substring(aStart, aEnd), b.toLowerCase().substring(bStart, bEnd));
Expand Down

0 comments on commit 182e906

Please sign in to comment.