| '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' ] |
| } |
| }); |