'use strict';
|
|
var common = require('../common');
|
var Type = require('../type');
|
|
function isHexCode(c) {
|
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
|
((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
|
((0x61/* a */ <= c) && (c <= 0x66/* f */));
|
}
|
|
function isOctCode(c) {
|
return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
|
}
|
|
function isDecCode(c) {
|
return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
|
}
|
|
function resolveYamlInteger(data) {
|
if (data === null) return false;
|
|
var max = data.length,
|
index = 0,
|
hasDigits = false,
|
ch;
|
|
if (!max) return false;
|
|
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) {
|
var value = data, sign = 1, ch, base, digits = [];
|
|
if (value.indexOf('_') !== -1) {
|
value = value.replace(/_/g, '');
|
}
|
|
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(function (v) {
|
digits.unshift(parseInt(v, 10));
|
});
|
|
value = 0;
|
base = 1;
|
|
digits.forEach(function (d) {
|
value += (d * base);
|
base *= 60;
|
});
|
|
return sign * value;
|
|
}
|
|
return sign * parseInt(value, 10);
|
}
|
|
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 ? '0' + obj.toString(8) : '-0' + obj.toString(8).slice(1); },
|
decimal: function (obj) { return obj.toString(10); },
|
/* eslint-disable max-len */
|
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' ]
|
}
|
});
|