184 lines
3.8 KiB
TypeScript
184 lines
3.8 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* This class has a very specific purpose:
|
|
*
|
|
* It can return convert offset within a decoded JSON string to offset within the encoded JSON string.
|
|
*/
|
|
export class JsonStringScanner {
|
|
private resultChars = 0;
|
|
private pos = 0;
|
|
|
|
/**
|
|
*
|
|
* @param text the encoded JSON string
|
|
* @param pos must not include ", ie must be `stringJSONNode.offset + 1`
|
|
*/
|
|
constructor(private readonly text: string, initialPos: number /* offset within `text` */) {
|
|
this.pos = initialPos;
|
|
}
|
|
|
|
// note that we don't do bound checks here, because we know that the offset is within the string
|
|
getOffsetInEncoded(offsetDecoded: number) {
|
|
|
|
let start = this.pos;
|
|
|
|
while (true) {
|
|
if (this.resultChars > offsetDecoded) {
|
|
return start;
|
|
}
|
|
|
|
const ch = this.text.charCodeAt(this.pos);
|
|
|
|
if (ch === CharacterCodes.backslash) {
|
|
start = this.pos;
|
|
this.pos++;
|
|
|
|
const ch2 = this.text.charCodeAt(this.pos++);
|
|
switch (ch2) {
|
|
case CharacterCodes.doubleQuote:
|
|
case CharacterCodes.backslash:
|
|
case CharacterCodes.slash:
|
|
case CharacterCodes.b:
|
|
case CharacterCodes.f:
|
|
case CharacterCodes.n:
|
|
case CharacterCodes.r:
|
|
case CharacterCodes.t:
|
|
this.resultChars += 1;
|
|
break;
|
|
case CharacterCodes.u: {
|
|
const ch3 = this.scanHexDigits(4, true);
|
|
if (ch3 >= 0) {
|
|
this.resultChars += String.fromCharCode(ch3).length;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
start = this.pos;
|
|
this.pos++;
|
|
this.resultChars++;
|
|
}
|
|
}
|
|
|
|
scanHexDigits(count: number, exact?: boolean): number {
|
|
let digits = 0;
|
|
let value = 0;
|
|
while (digits < count || !exact) {
|
|
const ch = this.text.charCodeAt(this.pos);
|
|
if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
|
|
value = value * 16 + ch - CharacterCodes._0;
|
|
}
|
|
else if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {
|
|
value = value * 16 + ch - CharacterCodes.A + 10;
|
|
}
|
|
else if (ch >= CharacterCodes.a && ch <= CharacterCodes.f) {
|
|
value = value * 16 + ch - CharacterCodes.a + 10;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
this.pos++;
|
|
digits++;
|
|
}
|
|
if (digits < count) {
|
|
value = -1;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
|
|
|
|
const enum CharacterCodes {
|
|
lineFeed = 0x0A, // \n
|
|
carriageReturn = 0x0D, // \r
|
|
|
|
space = 0x0020, // " "
|
|
|
|
_0 = 0x30,
|
|
_1 = 0x31,
|
|
_2 = 0x32,
|
|
_3 = 0x33,
|
|
_4 = 0x34,
|
|
_5 = 0x35,
|
|
_6 = 0x36,
|
|
_7 = 0x37,
|
|
_8 = 0x38,
|
|
_9 = 0x39,
|
|
|
|
a = 0x61,
|
|
b = 0x62,
|
|
c = 0x63,
|
|
d = 0x64,
|
|
e = 0x65,
|
|
f = 0x66,
|
|
g = 0x67,
|
|
h = 0x68,
|
|
i = 0x69,
|
|
j = 0x6A,
|
|
k = 0x6B,
|
|
l = 0x6C,
|
|
m = 0x6D,
|
|
n = 0x6E,
|
|
o = 0x6F,
|
|
p = 0x70,
|
|
q = 0x71,
|
|
r = 0x72,
|
|
s = 0x73,
|
|
t = 0x74,
|
|
u = 0x75,
|
|
v = 0x76,
|
|
w = 0x77,
|
|
x = 0x78,
|
|
y = 0x79,
|
|
z = 0x7A,
|
|
|
|
A = 0x41,
|
|
B = 0x42,
|
|
C = 0x43,
|
|
D = 0x44,
|
|
E = 0x45,
|
|
F = 0x46,
|
|
G = 0x47,
|
|
H = 0x48,
|
|
I = 0x49,
|
|
J = 0x4A,
|
|
K = 0x4B,
|
|
L = 0x4C,
|
|
M = 0x4D,
|
|
N = 0x4E,
|
|
O = 0x4F,
|
|
P = 0x50,
|
|
Q = 0x51,
|
|
R = 0x52,
|
|
S = 0x53,
|
|
T = 0x54,
|
|
U = 0x55,
|
|
V = 0x56,
|
|
W = 0x57,
|
|
X = 0x58,
|
|
Y = 0x59,
|
|
Z = 0x5a,
|
|
|
|
asterisk = 0x2A, // *
|
|
backslash = 0x5C, // \
|
|
closeBrace = 0x7D, // }
|
|
closeBracket = 0x5D, // ]
|
|
colon = 0x3A, // :
|
|
comma = 0x2C, // ,
|
|
dot = 0x2E, // .
|
|
doubleQuote = 0x22, // "
|
|
minus = 0x2D, // -
|
|
openBrace = 0x7B, // {
|
|
openBracket = 0x5B, // [
|
|
plus = 0x2B, // +
|
|
slash = 0x2F, // /
|
|
|
|
formFeed = 0x0C, // \f
|
|
tab = 0x09, // \t
|
|
}
|