Path: blob/main/extensions/extension-editing/src/jsonReconstruct.ts
3291 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45/**6* This class has a very specific purpose:7*8* It can return convert offset within a decoded JSON string to offset within the encoded JSON string.9*/10export class JsonStringScanner {11private resultChars = 0;12private pos = 0;1314/**15*16* @param text the encoded JSON string17* @param pos must not include ", ie must be `stringJSONNode.offset + 1`18*/19constructor(private readonly text: string, initialPos: number /* offset within `text` */) {20this.pos = initialPos;21}2223// note that we don't do bound checks here, because we know that the offset is within the string24getOffsetInEncoded(offsetDecoded: number) {2526let start = this.pos;2728while (true) {29if (this.resultChars > offsetDecoded) {30return start;31}3233const ch = this.text.charCodeAt(this.pos);3435if (ch === CharacterCodes.backslash) {36start = this.pos;37this.pos++;3839const ch2 = this.text.charCodeAt(this.pos++);40switch (ch2) {41case CharacterCodes.doubleQuote:42case CharacterCodes.backslash:43case CharacterCodes.slash:44case CharacterCodes.b:45case CharacterCodes.f:46case CharacterCodes.n:47case CharacterCodes.r:48case CharacterCodes.t:49this.resultChars += 1;50break;51case CharacterCodes.u: {52const ch3 = this.scanHexDigits(4, true);53if (ch3 >= 0) {54this.resultChars += String.fromCharCode(ch3).length;55}56break;57}58}59continue;60}61start = this.pos;62this.pos++;63this.resultChars++;64}65}6667scanHexDigits(count: number, exact?: boolean): number {68let digits = 0;69let value = 0;70while (digits < count || !exact) {71const ch = this.text.charCodeAt(this.pos);72if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {73value = value * 16 + ch - CharacterCodes._0;74}75else if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) {76value = value * 16 + ch - CharacterCodes.A + 10;77}78else if (ch >= CharacterCodes.a && ch <= CharacterCodes.f) {79value = value * 16 + ch - CharacterCodes.a + 10;80}81else {82break;83}84this.pos++;85digits++;86}87if (digits < count) {88value = -1;89}90return value;91}92}939495const enum CharacterCodes {96lineFeed = 0x0A, // \n97carriageReturn = 0x0D, // \r9899space = 0x0020, // " "100101_0 = 0x30,102_1 = 0x31,103_2 = 0x32,104_3 = 0x33,105_4 = 0x34,106_5 = 0x35,107_6 = 0x36,108_7 = 0x37,109_8 = 0x38,110_9 = 0x39,111112a = 0x61,113b = 0x62,114c = 0x63,115d = 0x64,116e = 0x65,117f = 0x66,118g = 0x67,119h = 0x68,120i = 0x69,121j = 0x6A,122k = 0x6B,123l = 0x6C,124m = 0x6D,125n = 0x6E,126o = 0x6F,127p = 0x70,128q = 0x71,129r = 0x72,130s = 0x73,131t = 0x74,132u = 0x75,133v = 0x76,134w = 0x77,135x = 0x78,136y = 0x79,137z = 0x7A,138139A = 0x41,140B = 0x42,141C = 0x43,142D = 0x44,143E = 0x45,144F = 0x46,145G = 0x47,146H = 0x48,147I = 0x49,148J = 0x4A,149K = 0x4B,150L = 0x4C,151M = 0x4D,152N = 0x4E,153O = 0x4F,154P = 0x50,155Q = 0x51,156R = 0x52,157S = 0x53,158T = 0x54,159U = 0x55,160V = 0x56,161W = 0x57,162X = 0x58,163Y = 0x59,164Z = 0x5a,165166asterisk = 0x2A, // *167backslash = 0x5C, // \168closeBrace = 0x7D, // }169closeBracket = 0x5D, // ]170colon = 0x3A, // :171comma = 0x2C, // ,172dot = 0x2E, // .173doubleQuote = 0x22, // "174minus = 0x2D, // -175openBrace = 0x7B, // {176openBracket = 0x5B, // [177plus = 0x2B, // +178slash = 0x2F, // /179180formFeed = 0x0C, // \f181tab = 0x09, // \t182}183184185