mirror of
https://github.com/swc-project/swc.git
synced 2024-12-21 04:32:01 +03:00
192 lines
4.4 KiB
TypeScript
192 lines
4.4 KiB
TypeScript
|
// Loaded from https://deno.land/std@0.78.0/encoding/_yaml/type/int.ts
|
||
|
|
||
|
|
||
|
// Ported from js-yaml v3.13.1:
|
||
|
// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
|
||
|
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
|
||
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||
|
|
||
|
import { Type } from "../type.ts";
|
||
|
import { Any, isNegativeZero } from "../utils.ts";
|
||
|
|
||
|
function isHexCode(c: number): boolean {
|
||
|
return (
|
||
|
(0x30 <= /* 0 */ c && c <= 0x39) /* 9 */ ||
|
||
|
(0x41 <= /* A */ c && c <= 0x46) /* F */ ||
|
||
|
(0x61 <= /* a */ c && c <= 0x66) /* f */
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function isOctCode(c: number): boolean {
|
||
|
return 0x30 <= /* 0 */ c && c <= 0x37 /* 7 */;
|
||
|
}
|
||
|
|
||
|
function isDecCode(c: number): boolean {
|
||
|
return 0x30 <= /* 0 */ c && c <= 0x39 /* 9 */;
|
||
|
}
|
||
|
|
||
|
function resolveYamlInteger(data: string): boolean {
|
||
|
const max = data.length;
|
||
|
let index = 0;
|
||
|
let hasDigits = false;
|
||
|
|
||
|
if (!max) return false;
|
||
|
|
||
|
let ch = data[index];
|
||
|
|
||
|
// sign
|
||
|
if (ch === "-" || ch === "+") {
|
||
|
ch = data[++index];
|
||
|
}
|
||
|
|
||
|
if (ch === "0") {
|
||
|
// 0
|
||
|
if (index + 1 === max) return true;
|
||
|
ch = data[++index];
|
||
|
|
||
|
// base 2, base 8, base 16
|
||
|
|
||
|
if (ch === "b") {
|
||
|
// base 2
|
||
|
index++;
|
||
|
|
||
|
for (; index < max; index++) {
|
||
|
ch = data[index];
|
||
|
if (ch === "_") continue;
|
||
|
if (ch !== "0" && ch !== "1") return false;
|
||
|
hasDigits = true;
|
||
|
}
|
||
|
return hasDigits && ch !== "_";
|
||
|
}
|
||
|
|
||
|
if (ch === "x") {
|
||
|
// base 16
|
||
|
index++;
|
||
|
|
||
|
for (; index < max; index++) {
|
||
|
ch = data[index];
|
||
|
if (ch === "_") continue;
|
||
|
if (!isHexCode(data.charCodeAt(index))) return false;
|
||
|
hasDigits = true;
|
||
|
}
|
||
|
return hasDigits && ch !== "_";
|
||
|
}
|
||
|
|
||
|
// base 8
|
||
|
for (; index < max; index++) {
|
||
|
ch = data[index];
|
||
|
if (ch === "_") continue;
|
||
|
if (!isOctCode(data.charCodeAt(index))) return false;
|
||
|
hasDigits = true;
|
||
|
}
|
||
|
return hasDigits && ch !== "_";
|
||
|
}
|
||
|
|
||
|
// base 10 (except 0) or base 60
|
||
|
|
||
|
// value should not start with `_`;
|
||
|
if (ch === "_") return false;
|
||
|
|
||
|
for (; index < max; index++) {
|
||
|
ch = data[index];
|
||
|
if (ch === "_") continue;
|
||
|
if (ch === ":") break;
|
||
|
if (!isDecCode(data.charCodeAt(index))) {
|
||
|
return false;
|
||
|
}
|
||
|
hasDigits = true;
|
||
|
}
|
||
|
|
||
|
// Should have digits and should not end with `_`
|
||
|
if (!hasDigits || ch === "_") return false;
|
||
|
|
||
|
// if !base60 - done;
|
||
|
if (ch !== ":") return true;
|
||
|
|
||
|
// base60 almost not used, no needs to optimize
|
||
|
return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
|
||
|
}
|
||
|
|
||
|
function constructYamlInteger(data: string): number {
|
||
|
let value = data;
|
||
|
const digits: number[] = [];
|
||
|
|
||
|
if (value.indexOf("_") !== -1) {
|
||
|
value = value.replace(/_/g, "");
|
||
|
}
|
||
|
|
||
|
let sign = 1;
|
||
|
let ch = value[0];
|
||
|
if (ch === "-" || ch === "+") {
|
||
|
if (ch === "-") sign = -1;
|
||
|
value = value.slice(1);
|
||
|
ch = value[0];
|
||
|
}
|
||
|
|
||
|
if (value === "0") return 0;
|
||
|
|
||
|
if (ch === "0") {
|
||
|
if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
|
||
|
if (value[1] === "x") return sign * parseInt(value, 16);
|
||
|
return sign * parseInt(value, 8);
|
||
|
}
|
||
|
|
||
|
if (value.indexOf(":") !== -1) {
|
||
|
value.split(":").forEach((v): void => {
|
||
|
digits.unshift(parseInt(v, 10));
|
||
|
});
|
||
|
|
||
|
let valueInt = 0;
|
||
|
let base = 1;
|
||
|
|
||
|
digits.forEach((d): void => {
|
||
|
valueInt += d * base;
|
||
|
base *= 60;
|
||
|
});
|
||
|
|
||
|
return sign * valueInt;
|
||
|
}
|
||
|
|
||
|
return sign * parseInt(value, 10);
|
||
|
}
|
||
|
|
||
|
function isInteger(object: Any): boolean {
|
||
|
return (
|
||
|
Object.prototype.toString.call(object) === "[object Number]" &&
|
||
|
object % 1 === 0 &&
|
||
|
!isNegativeZero(object)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
export const int = new Type("tag:yaml.org,2002:int", {
|
||
|
construct: constructYamlInteger,
|
||
|
defaultStyle: "decimal",
|
||
|
kind: "scalar",
|
||
|
predicate: isInteger,
|
||
|
represent: {
|
||
|
binary(obj: number): string {
|
||
|
return obj >= 0
|
||
|
? `0b${obj.toString(2)}`
|
||
|
: `-0b${obj.toString(2).slice(1)}`;
|
||
|
},
|
||
|
octal(obj: number): string {
|
||
|
return obj >= 0 ? `0${obj.toString(8)}` : `-0${obj.toString(8).slice(1)}`;
|
||
|
},
|
||
|
decimal(obj: number): string {
|
||
|
return obj.toString(10);
|
||
|
},
|
||
|
hexadecimal(obj: number): string {
|
||
|
return obj >= 0
|
||
|
? `0x${obj.toString(16).toUpperCase()}`
|
||
|
: `-0x${obj.toString(16).toUpperCase().slice(1)}`;
|
||
|
},
|
||
|
},
|
||
|
resolve: resolveYamlInteger,
|
||
|
styleAliases: {
|
||
|
binary: [2, "bin"],
|
||
|
decimal: [10, "dec"],
|
||
|
hexadecimal: [16, "hex"],
|
||
|
octal: [8, "oct"],
|
||
|
},
|
||
|
});
|