Introduce and adopt const enum CharCode for performance & readability

This commit is contained in:
Alex Dima 2016-09-12 17:37:47 +02:00
parent b3e928809e
commit 6fee06d69c
9 changed files with 114 additions and 64 deletions

View file

@ -13,6 +13,7 @@ import {isObject} from 'vs/base/common/types';
import {isChrome, isWebKit} from 'vs/base/browser/browser';
import {IKeyboardEvent, StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent';
import {IMouseEvent, StandardMouseEvent} from 'vs/base/browser/mouseEvent';
import {CharCode} from 'vs/base/common/charCode';
export function clearNode(node: HTMLElement) {
while (node.firstChild) {
@ -55,7 +56,6 @@ export function isInDOM(node: Node): boolean {
return false;
}
const _blank = ' '.charCodeAt(0);
let lastStart: number, lastEnd: number;
function _findClassName(node: HTMLElement, className: string): void {
@ -95,14 +95,14 @@ function _findClassName(node: HTMLElement, className: string): void {
idxEnd = idx + classLen;
// a class that is followed by another class
if ((idx === 0 || classes.charCodeAt(idx - 1) === _blank) && classes.charCodeAt(idxEnd) === _blank) {
if ((idx === 0 || classes.charCodeAt(idx - 1) === CharCode.Space) && classes.charCodeAt(idxEnd) === CharCode.Space) {
lastStart = idx;
lastEnd = idxEnd + 1;
return;
}
// last class
if (idx > 0 && classes.charCodeAt(idx - 1) === _blank && idxEnd === classesLen) {
if (idx > 0 && classes.charCodeAt(idx - 1) === CharCode.Space && idxEnd === classesLen) {
lastStart = idx - 1;
lastEnd = idxEnd;
return;

View file

@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
/**
* An inlined enum containing useful character codes (to be used with String.charCodeAt).
* Please leave the const keyword such that it gets inlined when compiled to JavaScript!
*/
export const enum CharCode {
Tab = 9,
LineFeed = 10,
CarriageReturn = 13,
Space = 32,
/**
* The `$` character.
*/
Dollar = 36,
/**
* The `/` character.
*/
Slash = 47,
Digit0 = 48,
Digit1 = 49,
Digit9 = 57,
/**
* The `:` character.
*/
Colon = 58,
A = 65,
Z = 90,
/**
* The `\` character.
*/
Backslash = 92,
/**
* The ``(`)`` character.
*/
BackTick = 96,
a = 97,
n = 110,
t = 116,
z = 122,
}

View file

@ -6,6 +6,7 @@
import strings = require('vs/base/common/strings');
import {BoundedLinkedMap} from 'vs/base/common/map';
import {CharCode} from 'vs/base/common/charCode';
export interface IFilter {
// Returns null if word doesn't match.
@ -114,19 +115,24 @@ function _matchesSubString(word: string, wordToMatchAgainst: string, i: number,
// CamelCase
function isLower(code: number): boolean {
return 97 <= code && code <= 122;
return CharCode.a <= code && code <= CharCode.z;
}
function isUpper(code: number): boolean {
return 65 <= code && code <= 90;
return CharCode.A <= code && code <= CharCode.Z;
}
function isNumber(code: number): boolean {
return 48 <= code && code <= 57;
return CharCode.Digit0 <= code && code <= CharCode.Digit9;
}
function isWhitespace(code: number): boolean {
return [32, 9, 10, 13].indexOf(code) > -1;
return (
code === CharCode.Space
|| code === CharCode.Tab
|| code === CharCode.LineFeed
|| code === CharCode.CarriageReturn
);
}
function isAlphanumeric(code: number): boolean {

View file

@ -7,6 +7,7 @@
import strings = require('vs/base/common/strings');
import paths = require('vs/base/common/paths');
import {BoundedLinkedMap} from 'vs/base/common/map';
import {CharCode} from 'vs/base/common/charCode';
export interface IExpression {
[pattern: string]: boolean | SiblingClause | any;
@ -467,9 +468,6 @@ function parseExpressionPattern(pattern: string, value: any): (ParsedStringPatte
return parsedPattern;
}
const SLASH = '/'.charCodeAt(0);
const BACKSLASH = '\\'.charCodeAt(0);
function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedExpressionPattern)[], result?: string): (ParsedStringPattern | ParsedExpressionPattern)[] {
const basenamePatterns = parsedPatterns.filter(parsedPattern => !!(<ParsedStringPattern>parsedPattern).basenames);
if (basenamePatterns.length < 2) {
@ -494,7 +492,7 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE
let i: number;
for (i = path.length; i > 0; i--) {
const ch = path.charCodeAt(i - 1);
if (ch === SLASH || ch === BACKSLASH) {
if (ch === CharCode.Slash || ch === CharCode.Backslash) {
break;
}
}

View file

@ -443,7 +443,7 @@ function isDigit(ch: number): boolean {
return ch >= CharacterCodes._0 && ch <= CharacterCodes._9;
}
enum CharacterCodes {
const enum CharacterCodes {
nullCharacter = 0,
maxAsciiCharacter = 0x7F,

View file

@ -5,6 +5,7 @@
'use strict';
import {isLinux, isWindows} from 'vs/base/common/platform';
import {CharCode} from 'vs/base/common/charCode';
/**
* The forward slash path separator.
@ -113,7 +114,7 @@ export function normalize(path: string, toOSPath?: boolean): string {
for (let end = root.length; end <= len; end++) {
// either at the end or at a path-separator character
if (end === len || path.charCodeAt(end) === _slash || path.charCodeAt(end) === _backslash) {
if (end === len || path.charCodeAt(end) === CharCode.Slash || path.charCodeAt(end) === CharCode.Backslash) {
if (streql(path, start, end, '..')) {
// skip current and remove parent (if there is already something)
@ -160,28 +161,28 @@ export function getRoot(path: string, sep: string = '/'): string {
let len = path.length;
let code = path.charCodeAt(0);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
code = path.charCodeAt(1);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
// UNC candidate \\localhost\shares\ddd
// ^^^^^^^^^^^^^^^^^^^
code = path.charCodeAt(2);
if (code !== _slash && code !== _backslash) {
if (code !== CharCode.Slash && code !== CharCode.Backslash) {
let pos = 3;
let start = pos;
for (; pos < len; pos++) {
code = path.charCodeAt(pos);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
break;
}
}
code = path.charCodeAt(pos + 1);
if (start !== pos && code !== _slash && code !== _backslash) {
if (start !== pos && code !== CharCode.Slash && code !== CharCode.Backslash) {
pos += 1;
for (; pos < len; pos++) {
code = path.charCodeAt(pos);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
return path.slice(0, pos + 1) // consume this separator
.replace(/[\\/]/g, sep);
}
@ -194,12 +195,12 @@ export function getRoot(path: string, sep: string = '/'): string {
// ^
return sep;
} else if ((code >= _A && code <= _Z) || (code >= _a && code <= _z)) {
} else if ((code >= CharCode.A && code <= CharCode.Z) || (code >= CharCode.a && code <= CharCode.z)) {
// check for windows drive letter c:\ or c:
if (path.charCodeAt(1) === _colon) {
if (path.charCodeAt(1) === CharCode.Colon) {
code = path.charCodeAt(2);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
// C:\fff
// ^^^
return path.slice(0, 2) + sep;
@ -219,7 +220,7 @@ export function getRoot(path: string, sep: string = '/'): string {
pos += 3; // 3 -> "://".length
for (; pos < len; pos++) {
code = path.charCodeAt(pos);
if (code === _slash || code === _backslash) {
if (code === CharCode.Slash || code === CharCode.Backslash) {
return path.slice(0, pos + 1); // consume this separator
}
}
@ -240,9 +241,9 @@ export const join: (...parts: string[]) => string = function () {
// add the separater between two parts unless
// there already is one
let last = value.charCodeAt(value.length - 1);
if (last !== _slash && last !== _backslash) {
if (last !== CharCode.Slash && last !== CharCode.Backslash) {
let next = part.charCodeAt(0);
if (next !== _slash && next !== _backslash) {
if (next !== CharCode.Slash && next !== CharCode.Backslash) {
value += sep;
}
@ -274,18 +275,18 @@ export function isUNC(path: string): boolean {
}
let code = path.charCodeAt(0);
if (code !== _backslash) {
if (code !== CharCode.Backslash) {
return false;
}
code = path.charCodeAt(1);
if (code !== _backslash) {
if (code !== CharCode.Backslash) {
return false;
}
let pos = 2;
let start = pos;
for (; pos < path.length; pos++) {
code = path.charCodeAt(pos);
if (code === _backslash) {
if (code === CharCode.Backslash) {
break;
}
}
@ -293,7 +294,7 @@ export function isUNC(path: string): boolean {
return false;
}
code = path.charCodeAt(pos + 1);
if (isNaN(code) || code === _backslash) {
if (isNaN(code) || code === CharCode.Backslash) {
return false;
}
return true;
@ -307,15 +308,6 @@ export function makePosixAbsolute(path: string): string {
return isPosixAbsolute(normalize(path)) ? path : sep + path;
}
const _slash = '/'.charCodeAt(0);
const _backslash = '\\'.charCodeAt(0);
const _colon = ':'.charCodeAt(0);
const _a = 'a'.charCodeAt(0);
const _A = 'A'.charCodeAt(0);
const _z = 'z'.charCodeAt(0);
const _Z = 'Z'.charCodeAt(0);
export function isEqualOrParent(path: string, candidate: string): boolean {
if (path === candidate) {
@ -327,7 +319,7 @@ export function isEqualOrParent(path: string, candidate: string): boolean {
let candidateLen = candidate.length;
let lastCandidateChar = candidate.charCodeAt(candidateLen - 1);
if (lastCandidateChar === _slash) {
if (lastCandidateChar === CharCode.Slash) {
candidate = candidate.substring(0, candidateLen - 1);
candidateLen -= 1;
}
@ -351,7 +343,7 @@ export function isEqualOrParent(path: string, candidate: string): boolean {
}
let char = path.charCodeAt(candidateLen);
return char === _slash;
return char === CharCode.Slash;
}
// Reference: https://en.wikipedia.org/wiki/Filename

View file

@ -5,6 +5,7 @@
'use strict';
import {BoundedLinkedMap} from 'vs/base/common/map';
import {CharCode} from 'vs/base/common/charCode';
/**
* The empty string.
@ -261,7 +262,8 @@ export function normalizeNFC(str: string): string {
*/
export function firstNonWhitespaceIndex(str: string): number {
for (let i = 0, len = str.length; i < len; i++) {
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
let chCode = str.charCodeAt(i);
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
return i;
}
}
@ -274,7 +276,8 @@ export function firstNonWhitespaceIndex(str: string): number {
*/
export function getLeadingWhitespace(str: string): string {
for (let i = 0, len = str.length; i < len; i++) {
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
let chCode = str.charCodeAt(i);
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
return str.substring(0, i);
}
}
@ -287,7 +290,8 @@ export function getLeadingWhitespace(str: string): string {
*/
export function lastNonWhitespaceIndex(str: string, startIndex: number = str.length - 1): number {
for (let i = startIndex; i >= 0; i--) {
if (str.charAt(i) !== ' ' && str.charAt(i) !== '\t') {
let chCode = str.charCodeAt(i);
if (chCode !== CharCode.Space && chCode !== CharCode.Tab) {
return i;
}
}
@ -305,7 +309,7 @@ export function compare(a: string, b: string): number {
}
function isAsciiChar(code: number): boolean {
return (code >= 97 && code <= 122) || (code >= 65 && code <= 90);
return (code >= CharCode.a && code <= CharCode.z) || (code >= CharCode.A && code <= CharCode.Z);
}
export function equalsIgnoreCase(a: string, b: string): boolean {

View file

@ -6,6 +6,7 @@
'use strict';
import sd = require('string_decoder');
import {CharCode} from 'vs/base/common/charCode';
/**
* Convenient way to iterate over output line by line. This helper accommodates for the fact that
@ -35,16 +36,16 @@ export class LineDecoder {
}
let start = 0;
let ch: number;
while (start < value.length && ((ch = value.charCodeAt(start)) === 13 || ch === 10)) {
while (start < value.length && ((ch = value.charCodeAt(start)) === CharCode.CarriageReturn || ch === CharCode.LineFeed)) {
start++;
}
let idx = start;
while (idx < value.length) {
ch = value.charCodeAt(idx);
if (ch === 13 || ch === 10) {
if (ch === CharCode.CarriageReturn || ch === CharCode.LineFeed) {
result.push(value.substring(start, idx));
idx++;
while (idx < value.length && ((ch = value.charCodeAt(idx)) === 13 || ch === 10)) {
while (idx < value.length && ((ch = value.charCodeAt(idx)) === CharCode.CarriageReturn || ch === CharCode.LineFeed)) {
idx++;
}
start = idx;

View file

@ -5,16 +5,10 @@
import * as strings from 'vs/base/common/strings';
import {IPatternInfo} from 'vs/platform/search/common/search';
import {CharCode} from 'vs/base/common/charCode';
const BACKSLASH_CHAR_CODE = '\\'.charCodeAt(0);
const DOLLAR_CHAR_CODE = '$'.charCodeAt(0);
const ZERO_CHAR_CODE = '0'.charCodeAt(0);
const ONE_CHAR_CODE = '1'.charCodeAt(0);
const NINE_CHAR_CODE = '9'.charCodeAt(0);
const BACK_TICK_CHAR_CODE = '`'.charCodeAt(0);
const SINGLE_QUOTE_CHAR_CODE = '`'.charCodeAt(0);
const n_CHAR_CODE = 'n'.charCodeAt(0);
const t_CHAR_CODE = 't'.charCodeAt(0);
export class ReplacePattern {
@ -91,7 +85,7 @@ export class ReplacePattern {
for (let i = 0, len = replaceString.length; i < len; i++) {
let chCode = replaceString.charCodeAt(i);
if (chCode === BACKSLASH_CHAR_CODE) {
if (chCode === CharCode.Backslash) {
// move to next char
i++;
@ -105,15 +99,15 @@ export class ReplacePattern {
let replaceWithCharacter: string = null;
switch (nextChCode) {
case BACKSLASH_CHAR_CODE:
case CharCode.Backslash:
// \\ => \
replaceWithCharacter = '\\';
break;
case n_CHAR_CODE:
case CharCode.n:
// \n => LF
replaceWithCharacter = '\n';
break;
case t_CHAR_CODE:
case CharCode.t:
// \t => TAB
replaceWithCharacter = '\t';
break;
@ -125,7 +119,7 @@ export class ReplacePattern {
}
}
if (chCode === DOLLAR_CHAR_CODE) {
if (chCode === CharCode.Dollar) {
// move to next char
i++;
@ -139,7 +133,7 @@ export class ReplacePattern {
let replaceWithCharacter: string = null;
switch (nextChCode) {
case ZERO_CHAR_CODE:
case CharCode.Digit0:
// $0 => $&
replaceWithCharacter = '$&';
this._hasParameters = true;
@ -150,7 +144,7 @@ export class ReplacePattern {
break;
default:
// check if it is a valid string parameter $n (0 <= n <= 99). $0 is already handled by now.
if (!this.between(nextChCode, ONE_CHAR_CODE, NINE_CHAR_CODE)) {
if (!this.between(nextChCode, CharCode.Digit1, CharCode.Digit9)) {
break;
}
if (i === replaceString.length - 1) {
@ -158,7 +152,7 @@ export class ReplacePattern {
break;
}
let charCode= replaceString.charCodeAt(++i);
if (!this.between(charCode, ZERO_CHAR_CODE, NINE_CHAR_CODE)) {
if (!this.between(charCode, CharCode.Digit0, CharCode.Digit9)) {
this._hasParameters = true;
--i;
break;
@ -168,7 +162,7 @@ export class ReplacePattern {
break;
}
charCode= replaceString.charCodeAt(++i);
if (!this.between(charCode, ZERO_CHAR_CODE, NINE_CHAR_CODE)) {
if (!this.between(charCode, CharCode.Digit0, CharCode.Digit9)) {
this._hasParameters = true;
--i;
break;
@ -195,4 +189,3 @@ export class ReplacePattern {
return from <= value && value <= to;
}
}