js-yaml
Version:
YAML 1.2 parser and serializer
143 lines (112 loc) • 3.35 kB
JavaScript
'use strict'
const common = require('../common')
const Type = require('../type')
function isHexCode (c) {
return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */)) ||
((c >= 0x41/* A */) && (c <= 0x46/* F */)) ||
((c >= 0x61/* a */) && (c <= 0x66/* f */))
}
function isOctCode (c) {
return ((c >= 0x30/* 0 */) && (c <= 0x37/* 7 */))
}
function isDecCode (c) {
return ((c >= 0x30/* 0 */) && (c <= 0x39/* 9 */))
}
function resolveYamlInteger (data) {
if (data === null) return false
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 !== '0' && ch !== '1') return false
hasDigits = true
}
return hasDigits && Number.isFinite(parseYamlInteger(data))
}
if (ch === 'x') {
// base 16
index++
for (; index < max; index++) {
if (!isHexCode(data.charCodeAt(index))) return false
hasDigits = true
}
return hasDigits && Number.isFinite(parseYamlInteger(data))
}
if (ch === 'o') {
// base 8
index++
for (; index < max; index++) {
if (!isOctCode(data.charCodeAt(index))) return false
hasDigits = true
}
return hasDigits && Number.isFinite(parseYamlInteger(data))
}
}
// base 10 (except 0)
for (; index < max; index++) {
if (!isDecCode(data.charCodeAt(index))) {
return false
}
hasDigits = true
}
if (!hasDigits) return false
return Number.isFinite(parseYamlInteger(data))
}
function parseYamlInteger (data) {
let value = data
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.slice(2), 16)
if (value[1] === 'o') return sign * parseInt(value.slice(2), 8)
}
return sign * parseInt(value, 10)
}
function constructYamlInteger (data) {
return parseYamlInteger(data)
}
function isInteger (object) {
return (Object.prototype.toString.call(object)) === '[object Number]' &&
(object % 1 === 0 && !common.isNegativeZero(object))
}
module.exports = new Type('tag:yaml.org,2002:int', {
kind: 'scalar',
resolve: resolveYamlInteger,
construct: constructYamlInteger,
predicate: isInteger,
represent: {
binary: function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1) },
octal: function (obj) { return obj >= 0 ? '0o' + obj.toString(8) : '-0o' + obj.toString(8).slice(1) },
decimal: function (obj) { return obj.toString(10) },
hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1) }
},
defaultStyle: 'decimal',
styleAliases: {
binary: [2, 'bin'],
octal: [8, 'oct'],
decimal: [10, 'dec'],
hexadecimal: [16, 'hex']
}
})