| Current Path : /home/deltalab/PMS/logistic-backend/node_modules/@angular-devkit/core/src/json/ |
| Current File : //home/deltalab/PMS/logistic-backend/node_modules/@angular-devkit/core/src/json/parser.js |
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseJson = exports.parseJsonAst = exports.JsonParseMode = exports.PathSpecificJsonException = exports.UnexpectedEndOfInputException = exports.InvalidJsonCharacterException = exports.JsonException = void 0;
/* eslint-disable no-constant-condition */
const exception_1 = require("../exception");
class JsonException extends exception_1.BaseException {
}
exports.JsonException = JsonException;
/**
* A character was invalid in this context.
* @deprecated
* @private
*/
class InvalidJsonCharacterException extends JsonException {
constructor(context) {
const pos = context.previous;
const invalidChar = JSON.stringify(_peek(context));
super(`Invalid JSON character: ${invalidChar} at ${pos.line}:${pos.character}.`);
this.invalidChar = invalidChar;
this.line = pos.line;
this.offset = pos.offset;
this.character = pos.character;
}
}
exports.InvalidJsonCharacterException = InvalidJsonCharacterException;
/**
* More input was expected, but we reached the end of the stream.
* @deprecated
* @private
*/
class UnexpectedEndOfInputException extends JsonException {
constructor(_context) {
super(`Unexpected end of file.`);
}
}
exports.UnexpectedEndOfInputException = UnexpectedEndOfInputException;
/**
* An error happened within a file.
* @deprecated Deprecated since version 11. Use 3rd party JSON parsers such as `jsonc-parser` instead.
*/
class PathSpecificJsonException extends JsonException {
constructor(path, exception) {
super(`An error happened at file path ${JSON.stringify(path)}: ${exception.message}`);
this.path = path;
this.exception = exception;
}
}
exports.PathSpecificJsonException = PathSpecificJsonException;
/**
* Peek and return the next character from the context.
* @private
*/
function _peek(context) {
return context.original[context.position.offset];
}
/**
* Move the context to the next character, including incrementing the line if necessary.
* @private
*/
function _next(context) {
context.previous = context.position;
let { offset, line, character } = context.position;
const char = context.original[offset];
offset++;
if (char == '\n') {
line++;
character = 0;
}
else {
character++;
}
context.position = { offset, line, character };
}
function _token(context, valid) {
const char = _peek(context);
if (valid) {
if (!char) {
throw new UnexpectedEndOfInputException(context);
}
if (valid.indexOf(char) == -1) {
throw new InvalidJsonCharacterException(context);
}
}
// Move the position of the context to the next character.
_next(context);
return char;
}
/**
* Read the exponent part of a number. The exponent part is looser for JSON than the number
* part. `str` is the string of the number itself found so far, and start the position
* where the full number started. Returns the node found.
* @private
*/
function _readExpNumber(context, start, str, comments) {
let char;
let signed = false;
while (true) {
char = _token(context);
if (char == '+' || char == '-') {
if (signed) {
break;
}
signed = true;
str += char;
}
else if (char == '0' ||
char == '1' ||
char == '2' ||
char == '3' ||
char == '4' ||
char == '5' ||
char == '6' ||
char == '7' ||
char == '8' ||
char == '9') {
signed = true;
str += char;
}
else {
break;
}
}
// We're done reading this number.
context.position = context.previous;
return {
kind: 'number',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
value: Number.parseFloat(str),
comments: comments,
};
}
/**
* Read the hexa part of a 0xBADCAFE hexadecimal number.
* @private
*/
function _readHexaNumber(context, isNegative, start, comments) {
// Read an hexadecimal number, until it's not hexadecimal.
let hexa = '';
const valid = '0123456789abcdefABCDEF';
for (let ch = _peek(context); ch && valid.includes(ch); ch = _peek(context)) {
// Add it to the hexa string.
hexa += ch;
// Move the position of the context to the next character.
_next(context);
}
const value = Number.parseInt(hexa, 16);
// We're done reading this number.
return {
kind: 'number',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
value: isNegative ? -value : value,
comments,
};
}
/**
* Read a number from the context.
* @private
*/
function _readNumber(context, comments = _readBlanks(context)) {
let str = '';
let dotted = false;
const start = context.position;
// read until `e` or end of line.
while (true) {
const char = _token(context);
// Read tokens, one by one.
if (char == '-') {
if (str != '') {
throw new InvalidJsonCharacterException(context);
}
}
else if (char == 'I' &&
(str == '-' || str == '' || str == '+') &&
(context.mode & JsonParseMode.NumberConstantsAllowed) != 0) {
// Infinity?
// _token(context, 'I'); Already read.
_token(context, 'n');
_token(context, 'f');
_token(context, 'i');
_token(context, 'n');
_token(context, 'i');
_token(context, 't');
_token(context, 'y');
str += 'Infinity';
break;
}
else if (char == '0') {
if (str == '0' || str == '-0') {
throw new InvalidJsonCharacterException(context);
}
}
else if (char == '1' ||
char == '2' ||
char == '3' ||
char == '4' ||
char == '5' ||
char == '6' ||
char == '7' ||
char == '8' ||
char == '9') {
if (str == '0' || str == '-0') {
throw new InvalidJsonCharacterException(context);
}
}
else if (char == '+' && str == '') {
// Pass over.
}
else if (char == '.') {
if (dotted) {
throw new InvalidJsonCharacterException(context);
}
dotted = true;
}
else if (char == 'e' || char == 'E') {
return _readExpNumber(context, start, str + char, comments);
}
else if (char == 'x' &&
(str == '0' || str == '-0') &&
(context.mode & JsonParseMode.HexadecimalNumberAllowed) != 0) {
return _readHexaNumber(context, str == '-0', start, comments);
}
else {
// We read one too many characters, so rollback the last character.
context.position = context.previous;
break;
}
str += char;
}
// We're done reading this number.
if (str.endsWith('.') && (context.mode & JsonParseMode.HexadecimalNumberAllowed) == 0) {
throw new InvalidJsonCharacterException(context);
}
return {
kind: 'number',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
value: Number.parseFloat(str),
comments,
};
}
/**
* Read a string from the context. Takes the comments of the string or read the blanks before the
* string.
* @private
*/
function _readString(context, comments = _readBlanks(context)) {
const start = context.position;
// Consume the first string delimiter.
const delim = _token(context);
if ((context.mode & JsonParseMode.SingleQuotesAllowed) == 0) {
if (delim == "'") {
throw new InvalidJsonCharacterException(context);
}
}
let str = '';
while (true) {
let char = _token(context);
if (char == delim) {
return {
kind: 'string',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
value: str,
comments: comments,
};
}
else if (char == '\\') {
char = _token(context);
switch (char) {
case '\\':
case '/':
case '"':
case delim:
str += char;
break;
case 'b':
str += '\b';
break;
case 'f':
str += '\f';
break;
case 'n':
str += '\n';
break;
case 'r':
str += '\r';
break;
case 't':
str += '\t';
break;
case 'u':
const [c0] = _token(context, '0123456789abcdefABCDEF');
const [c1] = _token(context, '0123456789abcdefABCDEF');
const [c2] = _token(context, '0123456789abcdefABCDEF');
const [c3] = _token(context, '0123456789abcdefABCDEF');
str += String.fromCharCode(parseInt(c0 + c1 + c2 + c3, 16));
break;
case undefined:
throw new UnexpectedEndOfInputException(context);
case '\n':
// Only valid when multiline strings are allowed.
if ((context.mode & JsonParseMode.MultiLineStringAllowed) == 0) {
throw new InvalidJsonCharacterException(context);
}
str += char;
break;
default:
throw new InvalidJsonCharacterException(context);
}
}
else if (char === undefined) {
throw new UnexpectedEndOfInputException(context);
}
else if (char == '\b' || char == '\f' || char == '\n' || char == '\r' || char == '\t') {
throw new InvalidJsonCharacterException(context);
}
else {
str += char;
}
}
}
/**
* Read the constant `true` from the context.
* @private
*/
function _readTrue(context, comments = _readBlanks(context)) {
const start = context.position;
_token(context, 't');
_token(context, 'r');
_token(context, 'u');
_token(context, 'e');
const end = context.position;
return {
kind: 'true',
start,
end,
text: context.original.substring(start.offset, end.offset),
value: true,
comments,
};
}
/**
* Read the constant `false` from the context.
* @private
*/
function _readFalse(context, comments = _readBlanks(context)) {
const start = context.position;
_token(context, 'f');
_token(context, 'a');
_token(context, 'l');
_token(context, 's');
_token(context, 'e');
const end = context.position;
return {
kind: 'false',
start,
end,
text: context.original.substring(start.offset, end.offset),
value: false,
comments,
};
}
/**
* Read the constant `null` from the context.
* @private
*/
function _readNull(context, comments = _readBlanks(context)) {
const start = context.position;
_token(context, 'n');
_token(context, 'u');
_token(context, 'l');
_token(context, 'l');
const end = context.position;
return {
kind: 'null',
start,
end,
text: context.original.substring(start.offset, end.offset),
value: null,
comments: comments,
};
}
/**
* Read the constant `NaN` from the context.
* @private
*/
function _readNaN(context, comments = _readBlanks(context)) {
const start = context.position;
_token(context, 'N');
_token(context, 'a');
_token(context, 'N');
const end = context.position;
return {
kind: 'number',
start,
end,
text: context.original.substring(start.offset, end.offset),
value: NaN,
comments: comments,
};
}
/**
* Read an array of JSON values from the context.
* @private
*/
function _readArray(context, comments = _readBlanks(context)) {
const start = context.position;
// Consume the first delimiter.
_token(context, '[');
const value = [];
const elements = [];
_readBlanks(context);
if (_peek(context) != ']') {
const node = _readValue(context);
elements.push(node);
value.push(node.value);
}
while (_peek(context) != ']') {
_token(context, ',');
const valueComments = _readBlanks(context);
if ((context.mode & JsonParseMode.TrailingCommasAllowed) !== 0 && _peek(context) === ']') {
break;
}
const node = _readValue(context, valueComments);
elements.push(node);
value.push(node.value);
}
_token(context, ']');
return {
kind: 'array',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
value,
elements,
comments,
};
}
/**
* Read an identifier from the context. An identifier is a valid JavaScript identifier, and this
* function is only used in Loose mode.
* @private
*/
function _readIdentifier(context, comments = _readBlanks(context)) {
const start = context.position;
let char = _peek(context);
if (char && '0123456789'.indexOf(char) != -1) {
const identifierNode = _readNumber(context);
return {
kind: 'identifier',
start,
end: identifierNode.end,
text: identifierNode.text,
value: identifierNode.value.toString(),
};
}
const identValidFirstChar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ';
const identValidChar = '_$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ0123456789';
let first = true;
let value = '';
while (true) {
char = _token(context);
if (char == undefined ||
(first ? identValidFirstChar.indexOf(char) : identValidChar.indexOf(char)) == -1) {
context.position = context.previous;
return {
kind: 'identifier',
start,
end: context.position,
text: context.original.substr(start.offset, context.position.offset),
value,
comments,
};
}
value += char;
first = false;
}
}
/**
* Read a property from the context. A property is a string or (in Loose mode only) a number or
* an identifier, followed by a colon `:`.
* @private
*/
function _readProperty(context, comments = _readBlanks(context)) {
const start = context.position;
let key;
if ((context.mode & JsonParseMode.IdentifierKeyNamesAllowed) != 0) {
const top = _peek(context);
if (top == '"' || top == "'") {
key = _readString(context);
}
else {
key = _readIdentifier(context);
}
}
else {
key = _readString(context);
}
_readBlanks(context);
_token(context, ':');
const value = _readValue(context);
const end = context.position;
return {
kind: 'keyvalue',
key,
value,
start,
end,
text: context.original.substring(start.offset, end.offset),
comments,
};
}
/**
* Read an object of properties -> JSON values from the context.
* @private
*/
function _readObject(context, comments = _readBlanks(context)) {
const start = context.position;
// Consume the first delimiter.
_token(context, '{');
const value = {};
const properties = [];
_readBlanks(context);
if (_peek(context) != '}') {
const property = _readProperty(context);
value[property.key.value] = property.value.value;
properties.push(property);
while (_peek(context) != '}') {
_token(context, ',');
const propertyComments = _readBlanks(context);
if ((context.mode & JsonParseMode.TrailingCommasAllowed) !== 0 && _peek(context) === '}') {
break;
}
const property = _readProperty(context, propertyComments);
value[property.key.value] = property.value.value;
properties.push(property);
}
}
_token(context, '}');
return {
kind: 'object',
properties,
start,
end: context.position,
value,
text: context.original.substring(start.offset, context.position.offset),
comments,
};
}
/**
* Remove any blank character or comments (in Loose mode) from the context, returning an array
* of comments if any are found.
* @private
*/
function _readBlanks(context) {
if ((context.mode & JsonParseMode.CommentsAllowed) != 0) {
const comments = [];
while (true) {
const char = context.original[context.position.offset];
if (char == '/' && context.original[context.position.offset + 1] == '*') {
const start = context.position;
// Multi line comment.
_next(context);
_next(context);
while (context.original[context.position.offset] != '*' ||
context.original[context.position.offset + 1] != '/') {
_next(context);
if (context.position.offset >= context.original.length) {
throw new UnexpectedEndOfInputException(context);
}
}
// Remove "*/".
_next(context);
_next(context);
comments.push({
kind: 'multicomment',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
content: context.original.substring(start.offset + 2, context.position.offset - 2),
});
}
else if (char == '/' && context.original[context.position.offset + 1] == '/') {
const start = context.position;
// Multi line comment.
_next(context);
_next(context);
while (context.original[context.position.offset] != '\n') {
_next(context);
if (context.position.offset >= context.original.length) {
break;
}
}
// Remove "\n".
if (context.position.offset < context.original.length) {
_next(context);
}
comments.push({
kind: 'comment',
start,
end: context.position,
text: context.original.substring(start.offset, context.position.offset),
content: context.original.substring(start.offset + 2, context.position.offset - 1),
});
}
else if (char == ' ' || char == '\t' || char == '\n' || char == '\r' || char == '\f') {
_next(context);
}
else {
break;
}
}
return comments;
}
else {
let char = context.original[context.position.offset];
while (char == ' ' || char == '\t' || char == '\n' || char == '\r' || char == '\f') {
_next(context);
char = context.original[context.position.offset];
}
return [];
}
}
/**
* Read a JSON value from the context, which can be any form of JSON value.
* @private
*/
function _readValue(context, comments = _readBlanks(context)) {
let result;
// Clean up before.
const char = _peek(context);
switch (char) {
case undefined:
throw new UnexpectedEndOfInputException(context);
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
result = _readNumber(context, comments);
break;
case '.':
case '+':
if ((context.mode & JsonParseMode.LaxNumberParsingAllowed) == 0) {
throw new InvalidJsonCharacterException(context);
}
result = _readNumber(context, comments);
break;
case "'":
case '"':
result = _readString(context, comments);
break;
case 'I':
if ((context.mode & JsonParseMode.NumberConstantsAllowed) == 0) {
throw new InvalidJsonCharacterException(context);
}
result = _readNumber(context, comments);
break;
case 'N':
if ((context.mode & JsonParseMode.NumberConstantsAllowed) == 0) {
throw new InvalidJsonCharacterException(context);
}
result = _readNaN(context, comments);
break;
case 't':
result = _readTrue(context, comments);
break;
case 'f':
result = _readFalse(context, comments);
break;
case 'n':
result = _readNull(context, comments);
break;
case '[':
result = _readArray(context, comments);
break;
case '{':
result = _readObject(context, comments);
break;
default:
throw new InvalidJsonCharacterException(context);
}
// Clean up after.
_readBlanks(context);
return result;
}
/**
* The Parse mode used for parsing the JSON string.
*/
var JsonParseMode;
(function (JsonParseMode) {
JsonParseMode[JsonParseMode["Strict"] = 0] = "Strict";
JsonParseMode[JsonParseMode["CommentsAllowed"] = 1] = "CommentsAllowed";
JsonParseMode[JsonParseMode["SingleQuotesAllowed"] = 2] = "SingleQuotesAllowed";
JsonParseMode[JsonParseMode["IdentifierKeyNamesAllowed"] = 4] = "IdentifierKeyNamesAllowed";
JsonParseMode[JsonParseMode["TrailingCommasAllowed"] = 8] = "TrailingCommasAllowed";
JsonParseMode[JsonParseMode["HexadecimalNumberAllowed"] = 16] = "HexadecimalNumberAllowed";
JsonParseMode[JsonParseMode["MultiLineStringAllowed"] = 32] = "MultiLineStringAllowed";
JsonParseMode[JsonParseMode["LaxNumberParsingAllowed"] = 64] = "LaxNumberParsingAllowed";
JsonParseMode[JsonParseMode["NumberConstantsAllowed"] = 128] = "NumberConstantsAllowed";
JsonParseMode[JsonParseMode["Default"] = 0] = "Default";
JsonParseMode[JsonParseMode["Loose"] = 255] = "Loose";
JsonParseMode[JsonParseMode["Json"] = 0] = "Json";
JsonParseMode[JsonParseMode["Json5"] = 255] = "Json5";
})(JsonParseMode = exports.JsonParseMode || (exports.JsonParseMode = {}));
/**
* Parse the JSON string and return its AST. The AST may be losing data (end comments are
* discarded for example, and space characters are not represented in the AST), but all values
* will have a single node in the AST (a 1-to-1 mapping).
*
* @deprecated Deprecated since version 11. Use 3rd party JSON parsers such as `jsonc-parser` instead.
* @param input The string to use.
* @param mode The mode to parse the input with. {@see JsonParseMode}.
* @returns {JsonAstNode} The root node of the value of the AST.
*/
function parseJsonAst(input, mode = JsonParseMode.Default) {
if (mode == JsonParseMode.Default) {
mode = JsonParseMode.Strict;
}
const context = {
position: { offset: 0, line: 0, character: 0 },
previous: { offset: 0, line: 0, character: 0 },
original: input,
comments: undefined,
mode,
};
const ast = _readValue(context);
if (context.position.offset < input.length) {
const rest = input.substr(context.position.offset);
const i = rest.length > 20 ? rest.substr(0, 20) + '...' : rest;
throw new Error(`Expected end of file, got "${i}" at ` +
`${context.position.line}:${context.position.character}.`);
}
return ast;
}
exports.parseJsonAst = parseJsonAst;
/**
* Parse a JSON string into its value. This discards the AST and only returns the value itself.
*
* If a path option is pass, it also absorbs JSON parsing errors and return a new error with the
* path in it. Useful for showing errors when parsing from a file.
*
* @deprecated Deprecated since version 11. Use 3rd party JSON parsers such as `jsonc-parser` instead.
* @param input The string to parse.
* @param mode The mode to parse the input with. {@see JsonParseMode}.
* @param options Additional optinos for parsing.
* @returns {JsonValue} The value represented by the JSON string.
*/
function parseJson(input, mode = JsonParseMode.Default, options) {
try {
// Try parsing for the fastest path available, if error, uses our own parser for better errors.
if (mode == JsonParseMode.Strict) {
try {
return JSON.parse(input);
}
catch (err) {
return parseJsonAst(input, mode).value;
}
}
return parseJsonAst(input, mode).value;
}
catch (e) {
if (options && options.path && e instanceof JsonException) {
throw new PathSpecificJsonException(options.path, e);
}
throw e;
}
}
exports.parseJson = parseJson;